diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..7ab80cbe --- /dev/null +++ b/.clang-format @@ -0,0 +1,41 @@ +--- +BasedOnStyle: Google +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: true +AlignTrailingComments: true +AllowShortBlocksOnASingleLine: true +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: WithoutElse +AlwaysBreakBeforeMultilineStrings: false +BinPackArguments: false +BinPackParameters: false +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: true +BreakStringLiterals: true +ColumnLimit: 100 +DerivePointerAlignment: false +IncludeBlocks: Regroup +IndentCaseLabels: true +IndentPPDirectives: BeforeHash +IndentWidth: 4 +IndentWrappedFunctionNames: true +Language: Cpp +MaxEmptyLinesToKeep: 2 +PointerAlignment: Middle +ReflowComments: true +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: Never + +... diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..8f5ed13c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +charset = utf-8 + +[*.yml] +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..2935d2bd --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# Sources +*.c text diff=c +*.h text diff=c +*.h linguist-language=C diff --git a/.github/workflows/os_test.yml b/.github/workflows/os_test.yml new file mode 100644 index 00000000..ddca8668 --- /dev/null +++ b/.github/workflows/os_test.yml @@ -0,0 +1,42 @@ +name: course_os test suite + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Cache Toolchain + id: cache-toolchain + uses: actions/cache@v1 + with: + path: toolchain + key: toolchain + + - name: Cache Qemu + id: cache-qemu + uses: actions/cache@v1 + with: + path: qemu/qemu + key: qemu + + - name: Install Dependencies + run: | + sudo apt-get update && + sudo apt-get install build-essential python3 wget texinfo zlib1g-dev -y + + - name: Build Toolchain + if: steps.cache-toolchain.outputs.cache-hit != 'true' + run: rm -rf toolchain/arm-none-eabi/ && make toolchain + + - name: Build Qemu + if: steps.cache-qemu.outputs.cache-hit != 'true' + run: rm -rf qemu/qemu* && make qemu + + - name: Compile + run: make build + + - name: Test + run: make test diff --git a/.gitignore b/.gitignore index 8c2fa405..e1d11917 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,65 @@ -#these were not originally apart of the repo -- appeared after build -/kernel/kernel.bin -/kernel/flash.bin -/kernel/boot-commands -/kernel/card.sd -/toolchain/target/ -/u-boot/u-boot-* +# Build files +kernel/kernel.bin +kernel/flash.bin +kernel/boot-commands +kernel/card.sd +kernel/src/test/test.c + +# Toolchain dir, but not the build script +/toolchain/ +!/toolchain/build.sh + +# Qemu dir, again without its buildscript /qemu/ !/qemu/build.sh +# Generic build dirs +build/ +/cmake-build-*/ + +# Generated docs +/docs/ +/html/ +/latex/ +/course_os_docs.pdf + +# Editor specific .settings/ .cproject .project +/.idea/ +!/.idea/runConfigurations +/.vscode/ +!/.idea/settings.json +*~ +*.swp +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist + +# CCLS files +.ccls-cache/ +compile_commands.json -#always exclude these from being pushed +# Binary files *.o *.img *.map *.elf *.bin -*~ -*.swp /user/hello/hello +/user/hello/hello1 +/user/hello/hello2 /user/libc/libc.a -[._]*.s[a-w][a-z] -[._]s[a-w][a-z] -*.un~ -Session.vim -.netrwhist +# Floobits (CLion collabrative editing plugin) +.floo +.flooignore +# Misc NOTES +/server.PID +compile_commands.json +user/swi/swi diff --git a/.idea/runConfigurations/debug.xml b/.idea/runConfigurations/debug.xml new file mode 100644 index 00000000..b7959806 --- /dev/null +++ b/.idea/runConfigurations/debug.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..275e2946 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "gdb", + "request": "attach", + "gdbpath": "${workspaceFolder}/toolchain/arm-none-eabi/bin/arm-none-eabi-gdb", + "name": "Debug", + "executable": "${workspaceFolder}/kernel/build/kernel.sym", + "target": ":1234", + "remote": true, + "cwd": "${workspaceRoot}", + // "preLaunchTask": "run_debug", + "valuesFormatting": "prettyPrinters" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..2ee84431 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "*.h": "c" + } +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..52d93342 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,24 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "make test", + "detail": "Runs the course_os test suite", + "type": "shell", + "command": "make test", + "problemMatcher": "$gcc", + "group": { + "kind": "test", + "isDefault": true + } + }, + { + "label": "run_debug", + "detail": "Runs qemu with gdbserver", + "type": "shell", + "command": "make -C kernel debug", + } + ] +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..376df43d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,32 @@ +######################################################################## +## WARNING: This cmake file does *NOT* work to compile the course OS ## +## It is merely here to make clion detect all the source files ## +## so it can do code inspection. Use the supplied makefile to compile ## +######################################################################## + +cmake_minimum_required(VERSION 3.6) + +project(course_os) + +set(CMAKE_SYSTEM_NAME linux) +set(CMAKE_SYSTEM_PROCESSOR arm) +set(CMAKE_C_COMPILER ${CMAKE_CURRENT_SOURCE_DIR}/toolchain/arm-none-eabi/bin/arm-none-eabi-gcc) +set(CMAKE_C_LINK_EXECUTABLE ${CMAKE_CURRENT_SOURCE_DIR}/toolchain/arm-none-eabi/bin/arm-none-eabi-ld) + +file(GLOB_RECURSE kernel_sources ./kernel/src/*.c ./kernel/src/**/*.c) +file(GLOB_RECURSE kernel_include LIST_DIRECTORIES true ./kernel/src/**/include) + +set(SOURCE_FILES ${kernel_sources}) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") + +add_compile_definitions(ENABLE_TESTS MEM_DEBUG) + +add_executable(course_os ${SOURCE_FILES}) + +message(${kernel_include}) + +include_directories( + ${kernel_include} +) + diff --git a/doxyfile b/Doxyfile similarity index 79% rename from doxyfile rename to Doxyfile index 706263ce..79283e15 100644 --- a/doxyfile +++ b/Doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.8.6 +# Doxyfile 1.8.15 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -17,11 +17,11 @@ # Project related configuration options #--------------------------------------------------------------------------- -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv -# for the list of possible encodings. +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 @@ -46,10 +46,10 @@ PROJECT_NUMBER = PROJECT_BRIEF = "Giving everyone a piece of the pi" -# With the PROJECT_LOGO tag one can specify an logo or icon that is included in -# the documentation. The maximum height of the logo should not exceed 55 pixels -# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo -# to the output directory. +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. PROJECT_LOGO = @@ -60,7 +60,7 @@ PROJECT_LOGO = OUTPUT_DIRECTORY = -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where @@ -68,7 +68,15 @@ OUTPUT_DIRECTORY = # performance problems for the file system. # The default value is: NO. -CREATE_SUBDIRS = NO +CREATE_SUBDIRS = YES + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = YES # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this @@ -85,14 +93,22 @@ CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the @@ -110,7 +126,17 @@ REPEAT_BRIEF = YES # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. -ABBREVIATE_BRIEF = +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief @@ -125,9 +151,9 @@ ALWAYS_DETAILED_SEC = NO # operators of the base classes will not be shown. # The default value is: NO. -INLINE_INHERITED_MEMB = NO +INLINE_INHERITED_MEMB = YES -# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. @@ -144,7 +170,7 @@ FULL_PATH_NAMES = YES # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = kernel/src/ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -169,7 +195,7 @@ SHORT_NAMES = NO # description.) # The default value is: NO. -JAVADOC_AUTOBRIEF = NO +JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If @@ -177,7 +203,7 @@ JAVADOC_AUTOBRIEF = NO # requiring an explicit \brief command for a brief description.) # The default value is: NO. -QT_AUTOBRIEF = NO +QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as @@ -197,9 +223,9 @@ MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a -# new page for each member. If set to NO, the documentation of a member will be -# part of the file/class/namespace that contains it. +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO @@ -218,7 +244,12 @@ TAB_SIZE = 4 # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) ALIASES = @@ -234,7 +265,7 @@ TCL_SUBST = # members will be omitted, etc. # The default value is: NO. -OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored @@ -256,16 +287,28 @@ OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is +# Fortran), use: inc=Fortran f=C. # -# Note For files without extension you can use no_extension as a placeholder. +# Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. @@ -274,7 +317,7 @@ EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. +# documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. @@ -282,10 +325,19 @@ EXTENSION_MAPPING = MARKDOWN_SUPPORT = YES +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 0. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 4 + # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by by putting a % sign in front of the word -# or globally by setting AUTOLINK_SUPPORT to NO. +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES @@ -298,7 +350,7 @@ AUTOLINK_SUPPORT = YES # diagrams that involve STL classes more complete and accurate. # The default value is: NO. -BUILTIN_STL_SUPPORT = NO +BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. @@ -307,7 +359,7 @@ BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. @@ -325,13 +377,20 @@ SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first +# tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = YES + # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent @@ -371,7 +430,7 @@ INLINE_SIMPLE_STRUCTS = NO # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. -TYPEDEF_HIDES_STRUCT = NO +TYPEDEF_HIDES_STRUCT = YES # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be @@ -390,7 +449,7 @@ LOOKUP_CACHE_SIZE = 0 # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. @@ -400,35 +459,35 @@ LOOKUP_CACHE_SIZE = 0 EXTRACT_ALL = YES -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. -EXTRACT_PRIVATE = NO +EXTRACT_PRIVATE = YES -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. -EXTRACT_PACKAGE = NO +EXTRACT_PACKAGE = YES -# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. -EXTRACT_STATIC = NO +EXTRACT_STATIC = YES -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local methods, +# This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO only methods in the interface are +# included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. @@ -453,21 +512,21 @@ HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set -# to NO these classes will be included in the various overviews. This option has -# no effect if EXTRACT_ALL is enabled. +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO these declarations will be +# (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO these +# documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. @@ -481,7 +540,7 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES upper-case letters are also +# names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. @@ -490,12 +549,19 @@ INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES the +# their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. @@ -523,14 +589,14 @@ INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member -# name. If set to NO the members will appear in declaration order. +# name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member -# name. If set to NO the members will appear in declaration order. Note that +# name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. @@ -575,27 +641,25 @@ SORT_BY_SCOPE_NAME = NO STRICT_PROTO_MATCHING = NO -# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the -# todo list. This list is created by putting \todo commands in the -# documentation. +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the -# test list. This list is created by putting \test commands in the -# documentation. +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. @@ -620,8 +684,8 @@ ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES the list -# will mention the files that were used to generate the documentation. +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES @@ -666,11 +730,10 @@ LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. Do not use file names with spaces, bibtex cannot handle them. See -# also \cite for info how to create references. +# search path. See also \cite for info how to create references. CITE_BIB_FILES = @@ -686,7 +749,7 @@ CITE_BIB_FILES = QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. @@ -694,7 +757,7 @@ QUIET = NO WARNINGS = YES -# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. @@ -711,11 +774,18 @@ WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return -# value. If set to NO doxygen will only warn about wrong or incomplete parameter -# documentation, but not about the absence of documentation. +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = YES + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. # The default value is: NO. -WARN_NO_PARAMDOC = NO +WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which @@ -740,15 +810,15 @@ WARN_LOGFILE = # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with -# spaces. +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = +INPUT = README.md kernel/src/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of # possible encodings. # The default value is: UTF-8. @@ -756,14 +826,64 @@ INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank the -# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, -# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, -# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, -# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, -# *.qsf, *.as and *.js. - -FILE_PATTERNS = +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.s \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. @@ -794,7 +914,7 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = */u-boot/* */toolchain/* */qemu/* +EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -818,7 +938,7 @@ EXAMPLE_PATH = # *.h) to filter out the source-files in the directories. If left blank all # files are included. -EXAMPLE_PATTERNS = +EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands @@ -847,6 +967,10 @@ IMAGE_PATH = # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. INPUT_FILTER = @@ -856,11 +980,15 @@ INPUT_FILTER = # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER ) will also be used to filter the input files that are used for +# INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. @@ -879,7 +1007,7 @@ FILTER_SOURCE_PATTERNS = # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = +USE_MDFILE_AS_MAINPAGE = README.md #--------------------------------------------------------------------------- # Configuration options related to source browsing @@ -892,35 +1020,35 @@ USE_MDFILE_AS_MAINPAGE = # also VERBATIM_HEADERS is set to NO. # The default value is: NO. -SOURCE_BROWSER = NO +SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. -INLINE_SOURCES = NO +INLINE_SOURCES = YES # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. -STRIP_CODE_COMMENTS = YES +STRIP_CODE_COMMENTS = NO # If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. +# entity all documented functions referencing it will be listed. # The default value is: NO. -REFERENCED_BY_RELATION = NO +REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. -REFERENCES_RELATION = NO +REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. @@ -940,12 +1068,12 @@ SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version +# (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # @@ -997,7 +1125,7 @@ IGNORE_PREFIX = # Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES @@ -1008,7 +1136,7 @@ GENERATE_HTML = YES # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_OUTPUT = html +HTML_OUTPUT = docs # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). @@ -1035,7 +1163,7 @@ HTML_FILE_EXTENSION = .html # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_HEADER = +HTML_HEADER = "doxygen_styles/html_header.html" # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard @@ -1045,7 +1173,7 @@ HTML_HEADER = # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_FOOTER = +HTML_FOOTER = "doxygen_styles/html_footer.html" # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of @@ -1059,16 +1187,19 @@ HTML_FOOTER = HTML_STYLESHEET = -# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- -# defined cascading style sheet that is included after the standard style sheets +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefor more robust against future updates. -# Doxygen will copy the style sheet file to the output directory. For an example -# see the documentation. +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = +HTML_EXTRA_STYLESHEET = "doxygen_styles/custom.css" \ + "doxygen_styles/custom_dark_theme.css" # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note @@ -1081,9 +1212,9 @@ HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the stylesheet and background images according to +# will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. @@ -1112,19 +1243,31 @@ HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: YES. +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_DYNAMIC_SECTIONS = NO +HTML_DYNAMIC_SECTIONS = YES # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand @@ -1141,13 +1284,13 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1186,7 +1329,7 @@ DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output @@ -1209,28 +1352,29 @@ GENERATE_HTMLHELP = NO CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = -# The GENERATE_CHI flag controls if a separate .chi index file is generated ( -# YES) or that it should be included in the master .chm file ( NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = -# The BINARY_TOC flag controls whether a binary table of contents is generated ( -# YES) or a normal table of contents ( NO) in the .chm file. +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1261,7 +1405,7 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1269,7 +1413,7 @@ QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1278,7 +1422,7 @@ QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1286,7 +1430,7 @@ QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1294,7 +1438,7 @@ QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = @@ -1343,7 +1487,7 @@ DISABLE_INDEX = NO # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has @@ -1352,7 +1496,7 @@ DISABLE_INDEX = NO # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_TREEVIEW = NO +GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. @@ -1369,9 +1513,9 @@ ENUM_VALUES_PER_LINE = 4 # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. -TREEVIEW_WIDTH = 250 +TREEVIEW_WIDTH = 350 -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1387,7 +1531,7 @@ EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # @@ -1399,8 +1543,8 @@ FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# https://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. @@ -1426,11 +1570,11 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. # This tag requires that the tag USE_MATHJAX is set to YES. -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest +MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example @@ -1470,11 +1614,11 @@ SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using Javascript. There -# are two flavours of web server based searching depending on the -# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for -# searching and an index file used by the script. When EXTERNAL_SEARCH is -# enabled the indexing and searching needs to be provided by external tools. See -# the section "External Indexing and Searching" for details. +# are two flavors of web server based searching depending on the EXTERNAL_SEARCH +# setting. When disabled, doxygen will generate a PHP script for searching and +# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing +# and searching needs to be provided by external tools. See the section +# "External Indexing and Searching" for details. # The default value is: NO. # This tag requires that the tag SEARCHENGINE is set to YES. @@ -1486,9 +1630,9 @@ SERVER_BASED_SEARCH = NO # external search engine pointed to by the SEARCHENGINE_URL option to obtain the # search results. # -# Doxygen ships with an example indexer ( doxyindexer) and search engine +# Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). +# Xapian (see: https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1499,9 +1643,9 @@ EXTERNAL_SEARCH = NO # The SEARCHENGINE_URL should point to a search engine hosted by a web server # which will return the search results when EXTERNAL_SEARCH is enabled. # -# Doxygen ships with an example indexer ( doxyindexer) and search engine +# Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). See the section "External Indexing and +# Xapian (see: https://xapian.org/). See the section "External Indexing and # Searching" for details. # This tag requires that the tag SEARCHENGINE is set to YES. @@ -1537,10 +1681,10 @@ EXTRA_SEARCH_MAPPINGS = # Configuration options related to the LaTeX output #--------------------------------------------------------------------------- -# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output. +# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. # The default value is: YES. -GENERATE_LATEX = YES +GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of @@ -1553,22 +1697,35 @@ LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. # -# Note that when enabling USE_PDFLATEX this option is only used for generating -# bitmaps for formulas in the HTML output, but not in the Makefile that is -# written to the output directory. -# The default file is: latex. +# Note that when not enabling USE_PDFLATEX the default is latex when enabling +# USE_PDFLATEX the default is pdflatex and when in the later case latex is +# chosen this is overwritten by pdflatex. For specific output languages the +# default can have been set differently, this depends on the implementation of +# the output language. # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_CMD_NAME = latex +LATEX_CMD_NAME = # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate # index for LaTeX. +# Note: This tag is used in the Makefile / make.bat. +# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file +# (.tex). # The default file is: makeindex. # This tag requires that the tag GENERATE_LATEX is set to YES. MAKEINDEX_CMD_NAME = makeindex -# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX +# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to +# generate index for LaTeX. +# Note: This tag is used in the generated output file (.tex). +# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. +# The default value is: \makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_MAKEINDEX_CMD = \makeindex + +# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX # documents. This may be useful for small projects and may help to save some # trees in general. # The default value is: NO. @@ -1586,9 +1743,12 @@ COMPACT_LATEX = NO PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names -# that should be included in the LaTeX output. To get the times font for -# instance you can specify -# EXTRA_PACKAGES=times +# that should be included in the LaTeX output. The package can be specified just +# by its name or with the correct syntax as to be used with the LaTeX +# \usepackage command. To get the times font for instance you can specify : +# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times} +# To use the option intlimits with the amsmath package you can specify: +# EXTRA_PACKAGES=[intlimits]{amsmath} # If left blank no extra packages will be included. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1602,23 +1762,36 @@ EXTRA_PACKAGES = # # Note: Only use a user-defined header if you know what you are doing! The # following commands have a special meaning inside the header: $title, -# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will -# replace them by respectively the title of the page, the current date and time, -# only the current date, the version number of doxygen, the project name (see -# PROJECT_NAME), or the project number (see PROJECT_NUMBER). +# $datetime, $date, $doxygenversion, $projectname, $projectnumber, +# $projectbrief, $projectlogo. Doxygen will replace $title with the empty +# string, for the replacement values of the other commands the user is referred +# to HTML_HEADER. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the # generated LaTeX document. The footer should contain everything after the last -# chapter. If it is left blank doxygen will generate a standard footer. +# chapter. If it is left blank doxygen will generate a standard footer. See +# LATEX_HEADER for more information on how to generate a default footer and what +# special commands can be used inside the footer. # # Note: Only use a user-defined footer if you know what you are doing! # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_FOOTER = +# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# LaTeX style sheets that are included after the standard style sheets created +# by doxygen. Using this option one can overrule certain style aspects. Doxygen +# will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_STYLESHEET = + # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the LATEX_OUTPUT output # directory. Note that the files will be copied as-is; there are no commands or @@ -1636,8 +1809,8 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES -# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate -# the PDF file directly from the LaTeX files. Set this option to YES to get a +# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate +# the PDF file directly from the LaTeX files. Set this option to YES, to get a # higher quality PDF documentation. # The default value is: YES. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1672,17 +1845,33 @@ LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See -# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# https://en.wikipedia.org/wiki/BibTeX and \cite for more info. # The default value is: plain. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_BIB_STYLE = plain +# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_TIMESTAMP = NO + +# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) +# path from which the emoji images will be read. If a relative path is entered, +# it will be relative to the LATEX_OUTPUT directory. If left blank the +# LATEX_OUTPUT directory will be used. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EMOJI_DIRECTORY = + #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- -# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The +# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The # RTF output is optimized for Word 97 and may not look too pretty with other RTF # readers/editors. # The default value is: NO. @@ -1697,7 +1886,7 @@ GENERATE_RTF = NO RTF_OUTPUT = rtf -# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF +# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF # documents. This may be useful for small projects and may help to save some # trees in general. # The default value is: NO. @@ -1717,9 +1906,9 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's config -# file, i.e. a series of assignments. You only have to provide replacements, -# missing definitions are set to their default value. +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# configuration file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. # # See also section "Doxygen usage" for information on how to generate the # default style sheet that doxygen normally uses. @@ -1728,17 +1917,27 @@ RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an RTF document. Syntax is -# similar to doxygen's config file. A template extensions file can be generated -# using doxygen -e rtf extensionFile. +# similar to doxygen's configuration file. A template extensions file can be +# generated using doxygen -e rtf extensionFile. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_EXTENSIONS_FILE = +# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code +# with syntax highlighting in the RTF output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_SOURCE_CODE = NO + #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- -# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for +# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for # classes and files. # The default value is: NO. @@ -1762,6 +1961,13 @@ MAN_OUTPUT = man MAN_EXTENSION = .3 +# The MAN_SUBDIR tag determines the name of the directory created within +# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by +# MAN_EXTENSION with the initial . removed. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_SUBDIR = + # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it # will generate one additional man file for each entity documented in the real # man page(s). These additional files only source the real man page, but without @@ -1775,7 +1981,7 @@ MAN_LINKS = NO # Configuration options related to the XML output #--------------------------------------------------------------------------- -# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that +# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that # captures the structure of the code including all documentation. # The default value is: NO. @@ -1789,19 +1995,7 @@ GENERATE_XML = NO XML_OUTPUT = xml -# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a -# validating XML parser to check the syntax of the XML files. -# This tag requires that the tag GENERATE_XML is set to YES. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify a XML DTD, which can be used by a -# validating XML parser to check the syntax of the XML files. -# This tag requires that the tag GENERATE_XML is set to YES. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program +# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program # listings (including syntax highlighting and cross-referencing information) to # the XML output. Note that enabling this will significantly increase the size # of the XML output. @@ -1810,11 +2004,18 @@ XML_DTD = XML_PROGRAMLISTING = YES +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include +# namespace members in file scope as well, matching the HTML output. +# The default value is: NO. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_NS_MEMB_FILE_SCOPE = NO + #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- -# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files +# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files # that can be used to generate PDF. # The default value is: NO. @@ -1828,14 +2029,23 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook +# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the +# program listings (including syntax highlighting and cross-referencing +# information) to the DOCBOOK output. Note that enabling this will significantly +# increase the size of the DOCBOOK output. +# The default value is: NO. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_PROGRAMLISTING = NO + #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- -# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen -# Definitions (see http://autogen.sf.net) file that captures the structure of -# the code including all documentation. Note that this feature is still -# experimental and incomplete at the moment. +# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an +# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# the structure of the code including all documentation. Note that this feature +# is still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO @@ -1844,7 +2054,7 @@ GENERATE_AUTOGEN_DEF = NO # Configuration options related to the Perl module output #--------------------------------------------------------------------------- -# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module +# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module # file that captures the structure of the code including all documentation. # # Note that this feature is still experimental and incomplete at the moment. @@ -1852,7 +2062,7 @@ GENERATE_AUTOGEN_DEF = NO GENERATE_PERLMOD = NO -# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary +# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary # Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI # output from the Perl module output. # The default value is: NO. @@ -1860,9 +2070,9 @@ GENERATE_PERLMOD = NO PERLMOD_LATEX = NO -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely +# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely # formatted so it can be parsed by a human reader. This is useful if you want to -# understand what is going on. On the other hand, if this tag is set to NO the +# understand what is going on. On the other hand, if this tag is set to NO, the # size of the Perl module output will be much smaller and Perl will parse it # just the same. # The default value is: YES. @@ -1882,14 +2092,14 @@ PERLMOD_MAKEVAR_PREFIX = # Configuration options related to the preprocessor #--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all +# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all # C-preprocessor directives found in the sources and include files. # The default value is: YES. ENABLE_PREPROCESSING = YES -# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names -# in the source code. If set to NO only conditional compilation will be +# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names +# in the source code. If set to NO, only conditional compilation will be # performed. Macro expansion can be done in a controlled way by setting # EXPAND_ONLY_PREDEF to YES. # The default value is: NO. @@ -1905,7 +2115,7 @@ MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO -# If the SEARCH_INCLUDES tag is set to YES the includes files in the +# If the SEARCH_INCLUDES tag is set to YES, the include files in the # INCLUDE_PATH will be searched if a #include is found. # The default value is: YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. @@ -1947,9 +2157,9 @@ PREDEFINED = EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will -# remove all refrences to function-like macros that are alone on a line, have an -# all uppercase name, and do not end with a semicolon. Such function macros are -# typically used for boiler-plate code, and will confuse the parser if not +# remove all references to function-like macros that are alone on a line, have +# an all uppercase name, and do not end with a semicolon. Such function macros +# are typically used for boiler-plate code, and will confuse the parser if not # removed. # The default value is: YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. @@ -1969,7 +2179,7 @@ SKIP_FUNCTION_MACROS = YES # where loc1 and loc2 can be relative or absolute paths or URLs. See the # section "Linking to external documentation" for more information about the use # of tag files. -# Note: Each tag file must have an unique name (where the name does NOT include +# Note: Each tag file must have a unique name (where the name does NOT include # the path). If a tag file is not located in the directory in which doxygen is # run, you must also specify the path to the tagfile here. @@ -1981,20 +2191,21 @@ TAGFILES = GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES all external class will be listed in the -# class index. If set to NO only the inherited external classes will be listed. +# If the ALLEXTERNALS tag is set to YES, all external class will be listed in +# the class index. If set to NO, only the inherited external classes will be +# listed. # The default value is: NO. ALLEXTERNALS = NO -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in -# the modules index. If set to NO, only the current project's groups will be +# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will be # listed. # The default value is: YES. EXTERNAL_GROUPS = YES -# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in +# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in # the related pages index. If set to NO, only the current project's pages will # be listed. # The default value is: YES. @@ -2011,7 +2222,7 @@ PERL_PATH = /usr/bin/perl # Configuration options related to the dot tool #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram +# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram # (in HTML and LaTeX) for classes with base or super classes. Setting the tag to # NO turns the diagrams off. Note that this option also works with HAVE_DOT # disabled, but it is recommended to install and use dot, since it yields more @@ -2036,7 +2247,7 @@ MSCGEN_PATH = DIA_PATH = -# If set to YES, the inheritance and collaboration graphs will hide inheritance +# If set to YES the inheritance and collaboration graphs will hide inheritance # and usage relations if the target is undocumented or is not a class. # The default value is: YES. @@ -2049,7 +2260,7 @@ HIDE_UNDOC_RELATIONS = YES # set to NO # The default value is: NO. -HAVE_DOT = NO +HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed # to run in parallel. When set to 0 doxygen will base this on the number of @@ -2061,7 +2272,7 @@ HAVE_DOT = NO DOT_NUM_THREADS = 0 -# When you want a differently looking font n the dot files that doxygen +# When you want a differently looking font in the dot files that doxygen # generates you can specify the font name using DOT_FONTNAME. You need to make # sure dot is able to find the font, which can be done by putting it in a # standard location or by setting the DOTFONTPATH environment variable or by @@ -2109,13 +2320,13 @@ COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -UML_LOOK = NO +UML_LOOK = YES # If the UML_LOOK tag is enabled, the fields and methods are shown inside the # class node. If there are many fields or methods and many nodes the graph may @@ -2161,22 +2372,24 @@ INCLUDED_BY_GRAPH = YES # # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. +# functions only using the \callgraph command. Disabling a call graph can be +# accomplished by means of the command \hidecallgraph. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -CALL_GRAPH = NO +CALL_GRAPH = YES # If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller # dependency graph for every global function or class method. # # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable caller graphs for selected -# functions only using the \callergraph command. +# functions only using the \callergraph command. Disabling a caller graph can be +# accomplished by means of the command \hidecallergraph. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -CALLER_GRAPH = NO +CALLER_GRAPH = YES # If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical # hierarchy of all classes instead of a textual one. @@ -2195,15 +2408,19 @@ GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. +# generated by dot. For an explanation of the image formats see the section +# output formats in the documentation of the dot tool (Graphviz (see: +# http://www.graphviz.org/)). # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # to make the SVG files visible in IE 9+ (other browsers do not have this # requirement). -# Possible values are: png, jpg, gif and svg. +# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo, +# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and +# png:gdiplus:gdiplus. # The default value is: png. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_IMAGE_FORMAT = png +DOT_IMAGE_FORMAT = svg # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. @@ -2215,7 +2432,7 @@ DOT_IMAGE_FORMAT = png # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -INTERACTIVE_SVG = NO +INTERACTIVE_SVG = YES # The DOT_PATH tag can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. @@ -2242,6 +2459,24 @@ MSCFILE_DIRS = DIAFILE_DIRS = +# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the +# path where java can find the plantuml.jar file. If left blank, it is assumed +# PlantUML is not used or called during a preprocessing step. Doxygen will +# generate a warning when it encounters a \startuml command in this case and +# will not generate output for the diagram. + +PLANTUML_JAR_PATH = + +# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for plantuml. + +PLANTUML_CFG_FILE = + +# When using plantuml, the specified paths are searched for files specified by +# the !include statement in a plantuml block. + +PLANTUML_INCLUDE_PATH = + # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes # that will be shown in the graph. If the number of nodes in a graph becomes # larger than this value, doxygen will truncate the graph, which is visualized @@ -2278,7 +2513,7 @@ MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) support # this, this feature is disabled by default. @@ -2295,7 +2530,7 @@ DOT_MULTI_TARGETS = YES GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot # files that are used to generate the various graphs. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. diff --git a/Makefile b/Makefile index ae3c04fa..25cce143 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,14 @@ -all: toolchain u-boot kernel +all: requirements kernel toolchain: cd ./toolchain && ./build.sh .PHONY: toolchain -u-boot: - $(MAKE) -C u-boot -.PHONY: u-boot +qemu: + cd ./qemu && ./build.sh +.PHONY: qemu + +requirements: toolchain qemu libc: $(MAKE) -C user/libc @@ -17,17 +19,20 @@ kernel: libc .PHONY: kernel clean: - $(MAKE) -C u-boot clean $(MAKE) -C kernel clean $(MAKE) -C user/libc clean $(MAKE) -C user/hello clean .PHONY: clean -build: u-boot kernel -run: + +build: + @$(MAKE) -C ./kernel build + +run: @$(MAKE) -C ./kernel run -.PHONY: run + +test: + @$(MAKE) -C ./kernel test docs: - doxygen doxyfile - $(MAKE) -C latex pdf - mv ./latex/refman.pdf course_os_docs.pdf + doxygen Doxyfile + xdg-open docs/index.html diff --git a/README.md b/README.md index 1478faef..cff7ceac 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,98 @@ -course_os -========= +![course_os test suite](https://github.com/rellermeyer/course_os/workflows/course_os%20test%20suite/badge.svg) -CS 439 course OS +# Course OS + +This is a 'toy' kernel created by students from multiple universities. +Currently it is mainly developed by students of the TU Delft. +It is targeted to run on the raspberry pi zero, b+ and 2. + +# Building + +[Build parameters](kernel/README.md) + +## Toolchain +To build and run the project, you will need a cross compiler. Since the kernel is made to run on ARM, the compiler has to output ARM instructions. + +To build the c toolchain for ARM, and `qemu-system-arm` version 4.20, run +```bash +make requirements +``` +from the root project directory. We build `qemu-system-arm` from source as this gives us better support +for attaching debuggers. Any up to date version of `qemu-system-arm` should work and if you already have this installed +through your package manager, just running +```bash +make toolchain +``` +should be sufficient. + +## Running + +After you built the toolchain, the kernel can be ran with: +```bash +make run +``` +from the root project directory, or from the `kernel` directory. + +## Running tests + +To run the test suite for the kernel, execute: + +```bash +make test +``` +from the root project directory, or from the `kernel` directory. + + +## Debugging + +To debug the kernel, you have to perform two steps. First you have to build and start the kernel with +```bash +make debug +``` + +from the `kernel` directory. This prepares qemu so it waits for a debugger to be attached. + +now, if you have CLion or VSCode you can run the supplied run configuration called `debug` which attaches a debugger, loads the sourcemap and runs the kernel. Now you can create breakpoints from within your IDE. + +If however you don't have either of those IDEs, or want to use gdb from a terminal, one can run the following command from the kernel directory: +```bash +make start_debug +``` + +# Creating tests + +To create tests for the kernel, please read [this](kernel/src/test/README.md) file. + +# Editors + +## CLion + +To open this project in CLion, you can simply create a new `c` project with the supplied `CMakeLists.txt` file. +This file can *not* be used to actually run the kernel but it does give clion the right instructions to make code completion etc. work. + +## Vim + CCLS + +To generate the required `compile_commands.json` so that CCLS correctly index the project. You have to do the following: + +First, generate the file using cmake: +```bash +cmake -H. -BDebug -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=YES +``` +Then, copy the file to the root folder: +```bash +cp Debug/compile_commands.json . +``` + +Afterwards you can remove the `Debug` folder with: +```bash +rm -rf Debug +``` + +Now Vim and CCLS will correctly know how to index the project. + + + +# Copyright Copyright (c) 2015, All rights reserved. diff --git a/config.mk b/config.mk index d1924e66..0ff9e2e6 100644 --- a/config.mk +++ b/config.mk @@ -3,10 +3,7 @@ TOOLCHAIN_DIR=toolchain BARE_METAL_TUPLE=arm-none-eabi BARE_METAL_TARGET:=$(BARE_METAL_TUPLE) -QEMU=qemu-system-arm - -#UBOOT_VERSION=2010.03 -UBOOT_VERSION=2014.10 +QEMU=./qemu/qemu/bin/qemu-system-arm #CFLAGS = -mcpu=arm1136j-s CFLAGS = -mcpu=arm1176jz-s diff --git a/kernel/vm/fastlz/LICENSE b/doxygen_styles/LICENSE similarity index 76% rename from kernel/vm/fastlz/LICENSE rename to doxygen_styles/LICENSE index 4a6abd6a..f671611b 100644 --- a/kernel/vm/fastlz/LICENSE +++ b/doxygen_styles/LICENSE @@ -1,8 +1,8 @@ -FastLZ - lightning-fast lossless compression library +License for the doxygen styles: +--- +MIT License -Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) -Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) -Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) +Copyright (c) 2019 Tilen Majerle Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -11,14 +11,14 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/doxygen_styles/custom.css b/doxygen_styles/custom.css new file mode 100644 index 00000000..ac39ccba --- /dev/null +++ b/doxygen_styles/custom.css @@ -0,0 +1,338 @@ +div.fragment, pre.fragment { + margin: 0; + padding: 4px; +} + +/*********************************************/ +/** Main content **/ +/*********************************************/ +.contents { + margin: 10px auto !important; + padding: 0 10px; + max-width: 1200px; +} + +/*********************************************/ +/** Inline code **/ +/*********************************************/ +p code, +li code, +td code, +dd code { + display: inline; + padding: 0px 6px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + + background-color: #CCCCCC; + border: 1px solid #333333; + + color: #333333; +} + +/*********************************************/ +/** Table of Contents (ToC) **/ +/*********************************************/ +div.toc { + margin: 0 !important; + border-radius: 4px !important; +} + +div.toc h3 { + font-size: 150%; + color: inherit; +} + +/*********************************************/ +/** Content table **/ +/*********************************************/ +.contents table.doxtable { + margin: 0 auto; +} + +/*********************************************/ +/** Field table **/ +/*********************************************/ +.fieldtable { + box-shadow: none !important; + -webkit-box-shadow: none; + -moz-box-shadow: none; +} + +/*********************************************/ +/** Memitem and memtitle **/ +/*********************************************/ +.memitem, +.memproto, +.memdoc { + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + background-image: none; +} + +/*********************************************/ +/** TOP navigation **/ +/*********************************************/ +.tablist a:hover, +.tablist li.current a { + text-shadow: none; + -moz-text-shadow: none; + -webkit-text-shadow: none; +} + +/*********************************************/ +/** H1 in textblocks **/ +/*********************************************/ +.textblock h1 { + border-bottom: 1px solid #32363d; + border-left: 3px solid #32363d; + margin: 40px 0px 10px 0px; + padding-bottom: 10px; + padding-top: 10px; + padding-left: 5px; +} + +.textblock h1:first-child { + margin-top: 10px; +} + +/*********************************************/ +/** Note, warning **/ +/*********************************************/ +dl.note, +dl.warning, +dl.todo, +dl.deprecated, +dl.reflist { + border: 0; + padding: 0px; + margin: 4px 0px 4px 0px; + border-radius: 4px; +} + +dl.note dt, +dl.warning dt, +dl.todo dt, +dl.deprecated dt, +dl.reflist dt { + margin: 0; + font-size: 14px; + padding: 2px 4px; + + border: none; + border-top-left-radius: 0px; + border-top-right-radius:0px; + + font-weight: bold; + text-transform: uppercase; + color: #FFFFFF !important; + + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + text-shadow: none; +} + +dl.note dd, +dl.warning dd, +dl.todo dd, +dl.deprecated dd, +dl.reflist dd { + margin: 0; + padding: 4px; + background: none; + + color: #222222; + + border: 1px solid; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + border-top: none; + + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + text-shadow: none; +} + +dl.reflist dd { + margin-bottom: 15px; +} + +/* Background colors */ +dl.note {} +dl.warning {} +dl.todo {} +dl.deprecated {} +dl.reflist {} + +/* Header */ +dl.note dt { + background-color: #cbc693; +} + +dl.warning dt { + background-color: #bf5f82; +} + +dl.todo dt { + background-color: #82b3c9; +} + +dl.deprecated dt { + background-color: #af8eb5; +} + +dl.reflist dt { + background-color: #cbae82; +} + +/* Content */ +dl.note dd { + background-color: #fff9c4; + border-color: #cbc693; +} + +dl.warning dd { + background-color: #f48fb1; + border-color: #bf5f82; +} + +dl.todo dd { + background-color: #b3e5fc; + border-color: #82b3c9; +} + +dl.deprecated dd { + background-color: #e1bee7; + border-color: #af8eb5; +} + +dl.reflist dd { + background-color: #ffe0b2; + border-color: #cbae82; +} + +/*********************************************/ +/** Reference list **/ +/**Similar to warning/note/todo/... messages**/ +/*********************************************/ +dl.reflist { + +} + +/*********************************************/ +/** Note, warning **/ +/*********************************************/ +#docs_list { + padding: 0 10px; +} + +#docs_list ul { + margin: 0; + padding: 0; + list-style: none; +} + +#docs_list ul li { + display: inline-block; + border-right: 1px solid #BFBFBF; +} + +#docs_list ul li:last-child { + border-right: none; +} + +#docs_list ul li a { + display: block; + padding: 8px 13px; + font-weight: bold; + font-size: 15px; +} + +#docs_list ul li a:hover, +#docs_list ul li a.docs_current { + text-decoration: underline; +} + +/*********************************************/ +/** Resizable UI **/ +/*********************************************/ +.ui-resizable-e { + width: 3px; +} + +/*********************************************/ +/** Download url **/ +/*********************************************/ +.download_url { + font-weight: bold; + font-size: 150%; + line-height: 150%; +} + +/*********************************************/ +/** Syntax folor **/ +/*********************************************/ +div.line a { + text-decoration: underline; +} + +span.lineno a { + text-decoration: none; +} + +/*********************************************/ +/** Modules/Directory table **/ +/*********************************************/ +.directory .arrow { + height: initial; +} + +.directory td.entry { + padding: 3px 6px; +} + +/*********************************************/ +/** Mem items **/ +/*********************************************/ +.memproto table td { + font-family: monospace, fixed !important; +} + +td.memItemLeft, td.memItemRight { + font-family: monospace, fixed; +} + +.paramname, .paramname em { + font-style: italic; +} + +.memdoc { + text-shadow: none; +} + +.memItem { + font-family: monospace, fixed; +} + +.memItem table { + font-family: inherit; +} + +/*********************************************/ +/** Footer **/ +/*********************************************/ +img.footer { + height: 22px; +} + +/*********************************************/ +/** Custom scrollbar **/ +/*********************************************/ + +/*********************************************/ +/** Custom scrollbar **/ +/*********************************************/ diff --git a/doxygen_styles/custom_dark_theme.css b/doxygen_styles/custom_dark_theme.css new file mode 100644 index 00000000..222adeeb --- /dev/null +++ b/doxygen_styles/custom_dark_theme.css @@ -0,0 +1,425 @@ +/* Light background: #3 5 3 6 2 9; */ +/* New light dark background #3 2 3 6 3 d */ +/* Dark background: #d f e 5 f 2; */ + +/* TOP MENU */ +.sm-dox { + background: #dfe5f2 !important; +} + +.sm-dox a { + background: none; +} + +body { + background: #282923; + background-image: none; + color: #D8D8D8; +} + +div.fragment, pre.fragment { + border: 1px solid #000000; + background: #32363d; +} + +a, a:link, a:visited { + color: #67d8ef !important; +} + +.highlighted { + background: none !important; +} + +a.highlighted { + background: none !important; +} + +/*********************************************/ +/** Top main menu **/ +/*********************************************/ +#main-nav { + /* display: none; */ + border-bottom: 1px solid #32363d; +} + +#main-nav .sm-dox { + background: transparent !important; +} + +.sm-dox a { + text-shadow: none !important; + background: transparent !important; +} + +.sm-dox a:hover { + background: #282923 !important; +} + +.sm-dox { + text-shadow: none !important; + box-shadow: none !important; +} + +.sm-dox ul { + border: 1px solid #000000; + background: #32363d; +} + +.directory tr.even { + background: #32363d; +} + + +/*********************************************/ +/** Top search **/ +/*********************************************/ +#MSearchSelectWindow { + border: 1px solid #000000; + background: #32363d; +} + +a.selectItem { + padding: 3px; +} + +a.SelectItem:hover { + background: #282923 !important; +} + +#MSearchResultsWindow { + border: 1px solid #000000; + background: #32363d; + color: #67d8ef !important;; +} + +/*********************************************/ +/** Main menu **/ +/*********************************************/ +#nav-tree { + background: transparent; +} + +#nav-tree .selected { + background-image: none; + background: #32363d; +} + +/*********************************************/ +/** Main content **/ +/*********************************************/ + +/*********************************************/ +/** Inline code **/ +/*********************************************/ +p code, +li code, +td code, +dd code { + background-color: #000000; + border: 1px solid #A8B8D9; + + color: #D8D8D8; +} + +/*********************************************/ +/** Table of Contents (ToC) **/ +/*********************************************/ +div.toc { + background: #32363d; + border: 1px solid #000000; +} + +div.toc h3 { + font-size: 150%; + color: inherit; +} + +/*********************************************/ +/** Content table **/ +/*********************************************/ +table.doxtable tr:nth-child(even) td { + background: #32363d; +} + +div.header { + background: transparent; + border-bottom: 1px solid #32363d; +} + +/*********************************************/ +/** Field table **/ +/*********************************************/ +.fieldtable th { + background: #282923; + color: inherit; +} + +/*********************************************/ +/** Memitem and memtitle **/ +/*********************************************/ +.memdoc { + border: 1px solid #A8B8D9; +} + +/*********************************************/ +/** TOP navigation **/ +/*********************************************/ +.tabs, .tabs2, .tabs3 { + background: #DDDDDD; +} + +.tablist li { + background: transparent !important; +} + +.tablist a { + background-image: none; + border-right: 1px solid #999999; + + color: #32363d; +} + +.tablist a:hover, +.tablist li.current a { + text-decoration: none; + color: #000000; + background: #CCCCCC; + background-image: none; +} + +/*********************************************/ +/** H1 in textblocks **/ +/*********************************************/ + +/*********************************************/ +/** Note, warning **/ +/*********************************************/ + +/*********************************************/ +/** Reference list **/ +/**Similar to warning/note/todo/... messages**/ +/*********************************************/ +dl.reflist { + +} + + +/*********************************************/ +/** Note, warning **/ +/*********************************************/ +#docs_list { + background: #32363d; +} + +#docs_list ul li { + border-right: 1px solid #BFBFBF; +} + +#docs_list ul li a { + color: #1b1e21; +} + +#docs_list ul li a:hover, +#docs_list ul li a.docs_current { + background: #282923; +} + +/*********************************************/ +/** Resizable UI **/ +/*********************************************/ +.ui-resizable-e { + background: #32363d; +} + +/*********************************************/ +/** Download url **/ +/*********************************************/ + +/*********************************************/ +/** Syntax folor **/ +/*********************************************/ +div.line { + background: transparent; + color: inherit; +} + +div.line a { + color: inherit; +} + +span.keyword { + color: #f92472; + font-style: italic; +} + +span.keywordtype { + color: #67cfc1; + font-style: italic; +} + +span.keywordflow { + color: #f92472; + font-style: italic; +} + +span.comment { + color: #74705a; +} + +span.preprocessor { + color: #a6e22b; +} + +span.stringliteral { + color: #e7db74; +} + +span.charliteral { + color: #e7db74; +} + +span.vhdldigit { + color: #ff00ff; +} + +span.vhdlchar { + color: #000000; +} + +span.vhdlkeyword { + color: #700070; +} + +span.vhdllogic { + color: #ff0000; +} + +span.lineno { + background: transparent; +} + +span.lineno a { + background: transparent; +} + +/*********************************************/ +/** Modules/Directory table **/ +/*********************************************/ +.mdescLeft, .mdescRight, .memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background: #32363d; + color: inherit; +} + +.memSeparator { + border: none; + background: transparent; +} + +h2.groupheader { + color: #67d8ef; +} + +/*********************************************/ +/** Mem items **/ +/*********************************************/ +.memtitle { + background: #32363d !important; + border-color: #000000; +} + +.memitem { + background: #32363d !important; + color: inherit; + text-shadow: none; +} + +.memproto { + background: inherit; + border-color: #000000; + color: inherit; + text-shadow: none; +} + +.memproto table td { + font-family: monospace, fixed !important; +} + +td.memItemLeft, td.memItemRight { + font-family: monospace, fixed; +} + +.paramname, .paramname em { + color: #bf5f82; +} + +.memdoc { + background: inherit; + border-color: #000000; +} + + +/*********************************************/ +/** Footer **/ +/*********************************************/ +.titlearea { + border-bottom: 1px solid #32363d; +} + +/*********************************************/ +/** Footer **/ +/*********************************************/ +#nav-path { + background: transparent; +} + +#nav-path ul { + background: transparent; + color: inherit; + border: none; + border-top: 1px solid #32363d; +} + +.navpath li.footer { + color: inherit; +} + +.navpath li.navelem a { + text-shadow: none; +} + +/*********************************************/ +/** Custom scrollbar **/ +/*********************************************/ +::-webkit-scrollbar { + width: 10px; +} + +/* Track */ +::-webkit-scrollbar-track { + border-radius: 10px; +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: #234567; + border: none; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: #32363d; +} + +/*********************************************/ +/** Custom scrollbar **/ +/*********************************************/ +h1.glow, h2.glow, h3.glow, +h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px #67d8ef; +} + + +iframe { + background-color: white; +} diff --git a/doxygen_styles/html_footer.html b/doxygen_styles/html_footer.html new file mode 100644 index 00000000..5cb35229 --- /dev/null +++ b/doxygen_styles/html_footer.html @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/doxygen_styles/html_header.html b/doxygen_styles/html_header.html new file mode 100644 index 00000000..7588e63b --- /dev/null +++ b/doxygen_styles/html_header.html @@ -0,0 +1,55 @@ + + + + + + + + $projectname: $title + $title + + + + $treeview + $search + $mathjax + + $extrastylesheet + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + +
+
$projectname +  $projectnumber +
+
$projectbrief
+
+
$projectbrief
+
$searchbox
+
+ + \ No newline at end of file diff --git a/kernel/.gdbinit b/kernel/.gdbinit deleted file mode 100644 index 04a23b5e..00000000 --- a/kernel/.gdbinit +++ /dev/null @@ -1,3 +0,0 @@ -add-symbol-file kernel.elf 0x00010000 -add-symbol-file kernel.elf 0xf0000000 -target remote localhost:1234 diff --git a/kernel/COPYRIGHT b/kernel/COPYRIGHT deleted file mode 100644 index af0a0fa3..00000000 --- a/kernel/COPYRIGHT +++ /dev/null @@ -1,297 +0,0 @@ - - - -musl - musl - an implementation of the standard library for Linux-based systems - - - - - - -
- - - - -
-summaryrefslogtreecommitdiff
- - - -
-
-
blob: a8a38a56305c70215c209330b85dbf5224b3a218 (plain) - - -
1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-
musl as a whole is licensed under the following standard MIT license:
-
-----------------------------------------------------------------------
-Copyright © 2005-2014 Rich Felker, et al.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------
-
-Authors/contributors include:
-
-Anthony G. Basile
-Arvid Picciani
-Bobby Bingham
-Boris Brezillon
-Chris Spiegel
-Emil Renner Berthing
-Hiltjo Posthuma
-Isaac Dunham
-Jens Gustedt
-Jeremy Huntwork
-John Spencer
-Justin Cormack
-Luca Barbato
-Luka Perkov
-Michael Forney
-Nicholas J. Kain
-orc
-Pascal Cuoq
-Pierre Carrier
-Rich Felker
-Richard Pennington
-Solar Designer
-Strake
-Szabolcs Nagy
-Timo Teräs
-Valentin Ochs
-William Haddon
-
-Portions of this software are derived from third-party works licensed
-under terms compatible with the above MIT license:
-
-The TRE regular expression implementation (src/regex/reg* and
-src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed
-under a 2-clause BSD license (license text in the source files). The
-included version has been heavily modified by Rich Felker in 2012, in
-the interests of size, simplicity, and namespace cleanliness.
-
-Much of the math library code (src/math/* and src/complex/*) is
-Copyright © 1993,2004 Sun Microsystems or
-Copyright © 2003-2011 David Schultz or
-Copyright © 2003-2009 Steven G. Kargl or
-Copyright © 2003-2009 Bruce D. Evans or
-Copyright © 2008 Stephen L. Moshier
-and labelled as such in comments in the individual source files. All
-have been licensed under extremely permissive terms.
-
-The ARM memcpy code (src/string/armel/memcpy.s) is Copyright © 2008
-The Android Open Source Project and is licensed under a two-clause BSD
-license. It was taken from Bionic libc, used on Android.
-
-The implementation of DES for crypt (src/misc/crypt_des.c) is
-Copyright © 1994 David Burren. It is licensed under a BSD license.
-
-The implementation of blowfish crypt (src/misc/crypt_blowfish.c) was
-originally written by Solar Designer and placed into the public
-domain. The code also comes with a fallback permissive license for use
-in jurisdictions that may not recognize the public domain.
-
-The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
-Valentin Ochs and is licensed under an MIT-style license.
-
-The BSD PRNG implementation (src/prng/random.c) and XSI search API
-(src/search/*.c) functions are Copyright © 2011 Szabolcs Nagy and
-licensed under following terms: "Permission to use, copy, modify,
-and/or distribute this code for any purpose with or without fee is
-hereby granted. There is no warranty."
-
-The x86_64 port was written by Nicholas J. Kain. Several files (crt)
-were released into the public domain; others are licensed under the
-standard MIT license terms at the top of this file. See individual
-files for their copyright status.
-
-The mips and microblaze ports were originally written by Richard
-Pennington for use in the ellcc project. The original code was adapted
-by Rich Felker for build system and code conventions during upstream
-integration. It is licensed under the standard MIT terms.
-
-The powerpc port was also originally written by Richard Pennington,
-and later supplemented and integrated by John Spencer. It is licensed
-under the standard MIT terms.
-
-All other files which have no copyright comments are original works
-produced specifically for use as part of this library, written either
-by Rich Felker, the main author of the library, or by one or more
-contibutors listed above. Details on authorship of individual files
-can be found in the git version control history of the project. The
-omission of copyright and license comments in each file is in the
-interest of source tree size.
-
-All public header files (include/* and arch/*/bits/*) should be
-treated as Public Domain as they intentionally contain no content
-which can be covered by copyright. Some source modules may fall in
-this category as well. If you believe that a file is so trivial that
-it should be in the Public Domain, please contact the authors and
-request an explicit statement releasing it from copyright.
-
-The following files are trivial, believed not to be copyrightable in
-the first place, and hereby explicitly released to the Public Domain:
-
-All public headers: include/*, arch/*/bits/*
-Startup files: crt/*
-
-
- -
- - diff --git a/kernel/Makefile b/kernel/Makefile index 4bb6b9dd..12cc339a 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,104 +1,109 @@ - include $(CURDIR)/../config.mk +# ===================== Configuration ===================== + +# TODO should we have "-nostdinc"? +# Flags to give to the c compiler +CFLAGS += -pipe -std=gnu99 -ffreestanding \ + -Wall -Werror -Wno-error=unused-function -Wno-error=unused-label -Wno-error=unused-parameter -Wno-error=unused-variable -Wno-error=unused-value -Wno-error=unused-local-typedefs \ + -g -O0 -mcpu=arm1176jzf-s -march=armv6zk -mfpu=vfp -fpic +#PI_CFLAGS = -mfpu=vfp -march=armv6zk -mtune=arm1176jzf-s -nostartfiles + +# variables to define in the preprocessor. +MEMORY = 1G +LOG_LEVEL ?= 4 +DEFINITIONS = MEM_DEBUG LOG_LEVEL=${LOG_LEVEL} +test: DEFINITIONS += ENABLE_TESTS # if we execute the test: rule, enable tests before recompiling +SOURCEDIR = src +BUILDDIR = build +# every directory named `include` will have its contents autoincluded +INCLUDEDIR = include +CPU = cortex-a7 + +# =================== End Configuration =================== + TOOLCHAIN_PATH:=$(CURDIR)/../$(TOOLCHAIN_DIR)/$(BARE_METAL_TARGET)/bin CC:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-gcc AS:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-as LD:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-gcc OBJCOPY:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-objcopy -MKIMAGE:=$(CURDIR)/../u-boot/u-boot-$(UBOOT_VERSION)/tools/mkimage GDB:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-gdb +QEMU := $(CURDIR)/../${QEMU} -PIOBJS = start.o pi_light.o startup.o drivers/uart_pi.o argparse.o klibc.o interrupt.o hw_handlers.o process.o elf.o loader.o memory/mem_alloc.o memory/allocator.o tests.o mmap.o vm/frame.o vm/vm.o drivers/timer.o data_structures/bitvector.o data_structures/array_list.o data_structures/priority_queue.o data_structures/linked_list.o data_structures/hash_map.o process/scheduler.o tests/test_mem_alloc.o tests/test_priority_queue.o tests/test_hash_map.o tests/test_vm.o fs/open_table.o fs/fat16/file.o tests/test_fs.o drivers/mmci.o +DIRS = $(shell find $(SOURCEDIR)/ -type d -print) +C_GEN_SOURCE_FILES := $(SOURCEDIR)/test/test.c +C_SOURCE_FILES := $(foreach dir,$(DIRS),$(wildcard $(dir)/*.c)) $(C_GEN_SOURCE_FILES) +C_OBJECT_FILES := $(patsubst $(SOURCEDIR)/%.c, \ + $(BUILDDIR)/%.o, $(C_SOURCE_FILES)) -OBJS=start.o drivers/uart.o startup.o argparse.o klibc.o interrupt.o hw_handlers.o process.o elf.o loader.o memory/mem_alloc.o memory/allocator.o tests.o mmap.o vm/frame.o vm/vm.o drivers/timer.o process/scheduler.o data_structures/bitvector.o data_structures/array_list.o data_structures/linked_list.o data_structures/priority_queue.o data_structures/hash_map.o tests/test_mem_alloc.o tests/test_priority_queue.o tests/test_hash_map.o tests/test_vm.o fs/open_table.o fs/fat16/file.o tests/test_fs.o drivers/mmci.o +S_SOURCE_FILES := $(foreach dir,$(DIRS),$(wildcard $(dir)/*.s)) +S_OBJECT_FILES := $(patsubst $(SOURCEDIR)/%.s, \ + $(BUILDDIR)/%.o, $(S_SOURCE_FILES)) -all: flash.bin card.sd +OBJECT_FILES := $(S_OBJECT_FILES) $(C_OBJECT_FILES) -make_Pi: kernelPi.img +INCLUDEDIRS := $(sort $(foreach dir, $(foreach dir1, $(DIRS), $(shell dirname $(dir1))), $(wildcard $(dir)/$(INCLUDEDIR)))) +CFLAGS += $(foreach dir, $(INCLUDEDIRS), -I./$(dir)) +CFLAGS += $(foreach def, $(DEFINITIONS), -D$(def)) -CFLAGS += -pipe -CFLAGS += -std=gnu99 -CFLAGS += -ffreestanding -CFLAGS += -nostdinc -CFLAGS += -Wall -CFLAGS += -Werror -PFLAGS += -mfpu=vfp -#PFLAGS += -mfloat-abi=hard -PFLAGS += -march=armv6zk -PFLAGS += -mtune=arm1176jzf-s -PFLAGS += -nostartfiles -CFLAGS += -g +build: $(BUILDDIR)/kernel.elf | builddir +build_pi: $(BUILDDIR)/kernelPi.img | builddir -run: flash.bin card.sd - ${QEMU} -M versatilepb -cpu arm1176 -sd card.sd -m 128M -nographic -kernel flash.bin -append "-load 0x410000 0x14000" +test: build | builddir + #${QEMU} -M versatilepb -cpu arm1176 -sd $(BUILDDIR)/card.sd -m $(MEMORY) -nographic -semihosting -kernel build/flash.bin -append "-load 0x410000 0x14000" + ${QEMU} -kernel $(BUILDDIR)/kernel.elf -m $(MEMORY) -serial stdio -monitor none -M raspi2 -cpu $(CPU) -nographic -append "-load 0x410000 0x14000" -semihosting -run-debug: flash.bin card.sd - ${QEMU} -S -s -M versatilepb -cpu arm1176 -sd card.sd -m 128M -nographic -kernel flash.bin -append "-load 0x410000 0x14000" +run: build | builddir + # nographic to turn off the gui + # monitor none to disable stdio monitoring so + # serial stdio works + #${QEMU} -M versatilepb -cpu arm1176 -sd $(BUILDDIR)/card.sd -m $(MEMORY) -nographic -semihosting -monitor none -serial stdio -kernel build/flash.bin -append "-load 0x410000 0x14000" + ${QEMU} -kernel $(BUILDDIR)/kernel.elf -m $(MEMORY) -serial stdio -monitor none -M raspi2 -cpu $(CPU) -nographic -append "-load 0x410000 0x14000" -semihosting -gdb: - ${GDB} -ex "target remote :1234" kernel.elf +debug: build | builddir + ${QEMU} -kernel $(BUILDDIR)/kernel.elf -m $(MEMORY) -serial stdio -monitor none -M raspi2 -cpu $(CPU) -nographic -append "-load 0x410000 0x14000" -semihosting -S -s -#boots the kernel at 0x210000 -flash.bin: kernel.img script.img - dd if=/dev/zero of=flash.bin bs=4k count=1536 - dd if=../u-boot/u-boot-$(UBOOT_VERSION)/u-boot.bin of=flash.bin conv=notrunc bs=4k - dd if=kernel.img of=flash.bin conv=notrunc bs=4k seek=512 - dd if=script.img of=flash.bin conv=notrunc bs=4k seek=575 +start_debug: build | builddir + $(GDB) -ex "target remote localhost:1234" -ex "symbol-file $(BUILDDIR)/kernel.sym" -# 32678*4096 = 128MiB -card.sd: fs-cmdline userhello - dd if=/dev/zero of=card.sd conv=notrunc bs=4096 count=32768 - fs/cmdline/buildfs ../user/hello/ +$(BUILDDIR)/kernel.elf: $(OBJECT_FILES) | builddir + $(LD) -T linker/kernel.ld -nostartfiles -Wl,-Map,kernel.map $^ -o $@ + $(OBJCOPY) --only-keep-debug $(BUILDDIR)/kernel.elf $(BUILDDIR)/kernel.sym + $(OBJCOPY) --strip-debug $(BUILDDIR)/kernel.elf -userhello: - make -C ../user/hello -fs-cmdline: - make -C fs/cmdline - -kernel.elf: $(OBJS) - $(LD) -T kernel.ld -nostartfiles -Wl,-Map,kernel.map $(OBJS) -o kernel.elf - -kernel.bin: kernel.elf - $(OBJCOPY) -O binary kernel.elf kernel.bin - -kernel.img: kernel.bin - $(MKIMAGE) -A arm -C none -O linux -T kernel -d kernel.bin -a 0x00010000 -e 0x00010000 kernel.img # Begin Pi Make -kernelPi.elf: $(PIOBJS) - $(CC) -T kernelPi.ld -O2 $(PFLAGS) $(PIOBJS) -o kernelPi.elf - -kernelPi.img: kernelPi.elf - $(OBJCOPY) kernelPi.elf -O binary kernelPi.img +$(BUILDDIR)/kernelPi.elf: $(C_OBJECT_FILES) | builddir + $(CC) -T kernelPi.ld -O2 $(PI_CFLAGS) $^ -o $@ +$(BUILDDIR)/kernelPi.img: $(BUILDDIR)/kernelPi.elf | builddir + $(OBJCOPY) $< -O binary $@ # End Pi Make -script.img: uboot-commands.ubt - $(MKIMAGE) -A arm -C none -T script -d uboot-commands.ubt -a 0x10000 -e 0x10000 script.img +builddir: + @mkdir -p $(BUILDDIR) -course_os.img: kernel.img - cat ../u-boot/u-boot-$(UBOOT_VERSION)/u-boot.bin kernel.img > course_os.img +$(BUILDDIR)/%.o: $(SOURCEDIR)/%.s | builddir + @mkdir -p $(shell dirname $@) + @echo Assembling $< + @$(AS) -mcpu=arm1176jzf-s -g $< -o $@ -startup.o: startup.s - $(AS) -mcpu=arm1176jzf-s -g startup.s -o startup.o +$(SOURCEDIR)/test/test.c: dummy | builddir + @echo Generating tests + @$(SOURCEDIR)/test/generate_tests.sh -%.o: %.c - $(CC) $(CFLAGS) -Iinclude -c $< -o $@ +# depend on dummy to always recompile. There aren't that many files atm anyway and +# when the definitions change, we have to recompile. TODO: move definitions to some kind of file +# so make knows that when it changed it should recompile. +$(BUILDDIR)/%.o: $(SOURCEDIR)/%.c dummy | builddir + @mkdir -p $(shell dirname $@) + @echo Compiling $< + @$(CC) $(CFLAGS) -c $< -o $@ clean: - rm -f $(OBJS) - rm -f *.img - rm -f *.elf - rm -f *.bin - rm -f *.map - rm -f drivers/*.o - rm -f fs/cmdline/buildfs - rm -f vm/*.o - rm -f tests/*.o - rm -f memory/*.o - rm -f data_structures/*.o - rm -f mq/*.o - @echo "I'm persisting the SD card 'card.sd', you'll have to remove that yourself if you want to rebuild it." - @echo "('rm sd.card')" + rm -rf $(BUILDDIR) + rm -rf $(SOURCEDIR)/test/test.c + +# use to force rebuild of certain recipes +dummy:; diff --git a/kernel/README.md b/kernel/README.md new file mode 100644 index 00000000..a2433cb1 --- /dev/null +++ b/kernel/README.md @@ -0,0 +1,24 @@ +# Running the kernel + +The [makefile](Makefile) in this directory contains a number of configuration options. + +| Configuration opion | description | +| --- | --- | +| CFLAGS | Flags given to the c compiler | +| MEMORY | The amount of memory given to qemu. Until memory detection works, must be `1G` | +| DEFINITIONS | These are variables given to the c preprocessor. Options for these are listed below. | +| KERNEL_PARAMS | Currently not supported and outdated | +| SOURCEDIR | The name of the directory containing the sourcecode. | +| BUILDDIR | The name of the directory containing object files and binaries | +| INCLUDEDIR | Any directory in SOURCEDIR with this name, will be globally included in every c file. This means they can be included with `#include ` instead of `#include "something.h"`. | +| TEST_MAIN_FILE | The name of the file generated to contain all [tests](src/test/README.md). | +| CPU | The cpu type emulated by qemu. Supported cpu types are the `arm1176` and `cortex-a7`| + + +## Definitions + +| Definition | Action | +| --- | --- | +| ENABLE_TESTS | With this definition enabled, tests are compiled into the kernel | +| MEM_DEBUG | Every kernel heap memory allocation (kmalloc, kfree) will be logged at TRACE level. Tests will be checked for memory leaks. | +| LOG_LEVEL | Number between 1 and 4 describing the log level of the kernel. 1 means only `WARN` logs. 2 means also `INFO` logs. 3 means also `DEBUG` logs and 4 means also `TRACE` logs. \ No newline at end of file diff --git a/kernel/argparse.c b/kernel/argparse.c deleted file mode 100644 index 6b2d0c4c..00000000 --- a/kernel/argparse.c +++ /dev/null @@ -1,171 +0,0 @@ -#include -#include "global_defs.h" -#include "argparse.h" -#include "klibc.h" -#include "tests.h" -#include "process.h" -#include "fs/file.h" - -static void argparse_parse(char *); - -/* Get the command-line arguments and run the functions to process them. */ -void argparse_process(uint32_t *p_bootargs) -{ - for (atag_iterator(tag, p_bootargs)) - { - os_printf("tag (+%d) %d\n", - (((uint32_t) ((uint32_t*) tag)) - ((uint32_t) p_bootargs)), - tag->header.tag); - atag_print(tag); - if (tag->header.tag == ATAG_CMDLINE) - { - argparse_parse((char*) &tag->content.cmdline.cmdline); - } - } -} - -void atag_print(struct atag *t) -{ - switch (t->header.tag) - { - case ATAG_CORE: - if (t->header.size == 2) - { - os_printf("ATAG_CORE\n"); - } - else - { - os_printf("ATAG_CORE (FLAGS=%d, PAGESIZE=%d, ROOTDEV=%d)\n", - t->content.core.flags, t->content.core.pagesize, - t->content.core.rootdev); - } - break; - case ATAG_MEM: - os_printf("ATAG_MEM (SIZE=%d, START=%d)\n", t->content.mem.size, - t->content.mem.start); - break; - case ATAG_CMDLINE: - os_printf("ATAG_CMDLINE (%s)\n", &t->content.cmdline.cmdline); - break; - } -} - -/* - Pulls name, start location, and size of file from command line - Opens file for process, then moves the process from - file to a location in memory. - Creates a process using the start location of process, - enables the VAS for the process, sets up the stack and heap, - then executes it. - @param Character pointer to command line - @param char* cmdline - - */ - -static void argparse_parse(char *cmdline) -{ - - char* token = os_strtok(cmdline, " "); - - while (token != NULL) - { - os_printf("token: %s\n", token); - - if (os_strcmp("-load", token) == 0) - { - char* name = os_strtok(NULL, " "); - - pcb* proc = process_create(name); - assert(proc != NULL); - process_execute(proc); - - } - else if (os_strcmp("-test", token) == 0) - { - os_printf("RUNNING TESTS\n"); - os_printf("Running tests...\n"); - Test *tests[2]; - tests[0] = create_test("This passes", &test1); - tests[1] = create_test("This fails", &test2); - run_tests(tests, 2); - } - - token = os_strtok(NULL, " "); - } -} - -/* We return a signed integer because we need a way to detect errors. - - Read a string of characters and interpret them as an unsigned integer. - Return -1 if the string cannot be read as an unsigned integer. - Return an integer representing the value of the string otherwise. - */ -int string_to_unsigned_int(char *input, int base) -{ - int i = os_strlen(input) - 1; // Index in the string - - if (hex_value_of_character(input[i]) == -1) - { - // Return -1 if the string cannot be read as an unsigned integer - return -1; - } - - int n = 0; // Number of digits - int result = 0; - - // Starting from the end of the string, read each character - while (i >= 0) - { - // Get the value of one character - int digit = hex_value_of_character(input[i]); - - if (digit == -1) - { - // If we hit a non-digit character such as 'x', return - return result; - } - - // Add the digit's value to the integer - result = result | (digit << (n * 4)); - - i--; - n++; - } - return result; -} - -/* Return the hexidecimal value of the single character c */ -int hex_value_of_character(char c) -{ - if (c >= '0' && c <= '9') - { - return (int) (c - '0'); - } - else if (c >= 'A' && c <= 'F') - { - return (int) (c - 'A' + 10); - } - else if (c >= 'a' && c <= 'f') - { - return (int) (c - 'a' + 10); - } - - // Return -1 if c was not a hex digit - return -1; -} - -uint32_t round_up(uint32_t c) -{ - - c--; - c |= c >> 1; - - c |= c >> 2; - c |= c >> 4; - c |= c >> 8; - - c |= c >> 16; - c++; - return c; - -} diff --git a/kernel/data_structures/array_list.c b/kernel/data_structures/array_list.c deleted file mode 100644 index c09fd10e..00000000 --- a/kernel/data_structures/array_list.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * array_list.c - * - * Created on: Apr 21, 2015 - * Author: kittenRainbow - */ - -#include "data_structures/array_list.h" - -arrl_handle* arrl_create() { - return arrl_create_fixed(DEFAULT_BUCKET_SIZE); -} - -arrl_handle* arrl_create_fixed(uint32_t bucket_size) { - arrl_handle* result = (arrl_handle *) kmalloc(sizeof(arrl_handle)); - void** bucket = kmalloc(bucket_size * sizeof(void*)); - llist_handle * l = llist_create(bucket); - result->linked_list = l; - result->size = 0; - result->capacity = bucket_size; - return result; -} - -void arrl_append(arrl_handle* arrl, void* elem) { - llist_node * curr_bucket; - uint32_t list_size; - uint32_t last_bucket_size; - - if (arrl->capacity == arrl->size) { - void* data = kmalloc(arrl->bucket_size * sizeof(void*)); - llist_enqueue(arrl->linked_list, data); - arrl->capacity += arrl->bucket_size; - } - - curr_bucket = arrl->linked_list->head; - list_size = arrl->size / arrl->bucket_size; - last_bucket_size = arrl->size % arrl->bucket_size; - - for(uint32_t i=0; i < list_size; ++i) { - curr_bucket= curr_bucket->next; - } - *(((int**)curr_bucket->data) + last_bucket_size) = (int*)elem; -} - -void arrl_remove(arrl_handle* arrl, void* elem) { - uint32_t bucket_size; - uint32_t list_size; - uint32_t bucket_index; - uint32_t list_index; - llist_node* curr_bucket; - llist_node* tail; - - bucket_size = arrl->bucket_size; - list_size = arrl->linked_list->count; - curr_bucket = arrl->linked_list->head; - tail = arrl->linked_list->tail; - - for (list_index = 0; list_index < list_size; ++list_index) { - for (bucket_index = 0; bucket_index < bucket_size; ++bucket_index) { - //if (elem == curr_bucket->data[bucket_index]) { - kfree(elem); - goto out; - //} - } - curr_bucket = curr_bucket->next; - } - - // Except the last bucket, shift each bucket up by one and copy first element of the next bucket to the last cell of the current bucket - out: while (curr_bucket != tail) { - os_memcpy(*(((uint32_t**)curr_bucket->data) + bucket_index + 1), - *(((uint32_t**)curr_bucket->data) + bucket_index + 0), - bucket_size - bucket_index - 1); - bucket_index = 0; - *(((int**)curr_bucket->data) + bucket_size - 1) = *((int**)curr_bucket->next->data); - curr_bucket = curr_bucket->next; - } - - --arrl->size; -} - -uint32_t arrl_contains(arrl_handle* arrl, void* elem) { - uint32_t bucket_size = arrl->bucket_size; - uint32_t list_size = arrl->linked_list->count; - llist_node* bucket = arrl->linked_list->head; - - for (uint32_t list_index = 0; list_index < list_size; ++list_index) { - for (uint32_t bucket_index = 0; bucket_index < bucket_size; - ++bucket_index) { - //if (elem == bucket->data[bucket_index]) { - return 1; - //} - } - bucket = bucket->next; - } - return 0; -} - -uint32_t arrl_index_of(arrl_handle* arrl, void* elem) { - int bucket_size = arrl->bucket_size; - int list_size = arrl->linked_list->count; - llist_node* bucket = arrl->linked_list->head; - - for (int list_index = 0; list_index < list_size; ++list_index) { - for (int bucket_index = 0; bucket_index < bucket_size; - ++bucket_index) { - //if (elem == bucket->data[bucket_index]) { - return list_index * DEFAULT_BUCKET_SIZE + bucket_index; - //} - } - bucket = bucket->next; - } - return -1; -} - -uint32_t arrl_count(arrl_handle* arrl) { - return arrl->size; -} - diff --git a/kernel/data_structures/bin_tree.c b/kernel/data_structures/bin_tree.c deleted file mode 100644 index cef924b4..00000000 --- a/kernel/data_structures/bin_tree.c +++ /dev/null @@ -1,287 +0,0 @@ -/******************************************************************** - * bin_tree.c - * - * Authors: Brandon Olivier, Collin Massey // any collaborators, please add name - * - * Created: 19 April 2014 - * - * Last edit: 27 November 2015 - * - * Purpose: Implement unbalanced binary trees for addresses - * - ********************************************************************/ -//#include "klibc.h" -//#include "data_structures/bin_tree.h" -#include -#include - - -typedef struct node { - struct node *parent; - struct node *left; - struct node *right; - void *data; -} node; - -typedef struct tree { - struct node *root; - int size; -} tree; - - -struct tree *new_tree(node *root) -{ - struct tree *t = (tree *)kmalloc(sizeof(struct tree)); // TODO: Needs to be fixed - t->root = root; - t->size = 0; - return t; -} - -struct tree *init_tree() -{ - return new_tree(NULL); -} - -// Compare 2 values -int comparison(void *a, void *b) -{ - int x = *(int *)a; - int y = *(int *)b; - if (x < y) - return -1; - if (x > y) - return 1; - return 0; // x = y (a = b) -} - -// Insert a node into the tree if not already present -// Returns 1 if inserted, 0 otherwise -int insert(tree *t, void *val) -{ - if (contains_node(t, val)) { - return 0; - } - - struct node *new_node = (node *)kmalloc(sizeof(struct node)); // TODO: Needs to be fixed - new_node->left = new_node->right = NULL; - new_node->parent = NULL; - new_node->data = val; - - if (t->root == NULL) { // Empty tree - t->root = new_node; - t->size += 1; - return 1; - } - - node *parent = NULL; // Will be parent of new node - node *temp = t->root; // Temporary node - int comp = 0; // Comparison value, used in final step - - // Traverse tree - while(temp) { - parent = temp; - switch (comparison(temp->data, val)) { - case 1: - comp = 1; - temp = temp->left; - break; - case -1: - comp = -1; - temp = temp->right; - break; - case 0: // This should never hit, but just in case - return 0; - default: - return 0; // Undefined behavior - } - } - - // Add node to tree - if (comp == 1) { - parent->left = new_node; - } else { // comp = -1 - parent->right = new_node; - } - - new_node->parent = parent; // Each node know its parent - t->size += 1; - return 1; -} - -// Returns the node that has data = val if present, NULL otherwise -node *find_node(tree *t, void *val) -{ - node *current_node = t->root; - - while (current_node) { - switch (comparison(¤t_node->data, val)) { - case -1: - current_node = current_node->right; - break; - case 1: - current_node = current_node->left; - break; - case 0: - return current_node; - default: - return NULL; // Undefined behavior - } - } - - // val not found - return NULL; -} - -// Returns 1 if the tree contains a node with data = val, 0 otherwise -int contains_node(tree *t, void *val) -{ - return find_node(t, val) != NULL ? 1 : 0; -} - -// Returns the node with the minimum value in the tree provided -// If tree is empty, returns NULL -node *min_node(tree *t) -{ - node *temp = t->root; - - while (temp->left != NULL) { - temp = temp->left; - } - - return temp; -} - -// Returns the minimum value in the tree, or 0 if not present -int min_val(tree *t) -{ - node *n = min_node(t); - return n != NULL ? *((int *)n->data) : 0; -} - -// Returns the node with the maximum value in the tree provided -// If tree is empty, returns NULL -node *max_node(tree *t) -{ - node *temp = t->root; - - while (temp->right != NULL) { - temp = temp->right; - } - - return temp; -} - -// Returns the maximum value in the tree, or 0 if not present -int max_val(tree *t) -{ - node *n = max_node(t); - return n != NULL ? *((int *)n->data) : 0; -} - -// Remove node with data = val from tree if present -// Returns 1 if removed, 0 if node not present -int remove_node(tree *t, void *val) -{ - node *n = find_node(t, val); - if (n == NULL) // node not present - return 0; - - node *parent = n->parent; - int children = 0; // # of children n has - - if (n->left != NULL) - children += 1; - if (n->right != NULL) - children += 1; - - if (children == 0) { // Most simple - if (parent->left == n) { - parent->left = NULL; - } else { - parent->right = NULL; - } - - kfree(n); - t->size -= 1; - return 1; - } else if (children == 1) { // Less simple - if (parent->left == n) { - if (n->left != NULL) { - parent->left = n->left; - } else { - parent->left = n->right; - } - } else { - if (n->left != NULL) { - parent->right = n->left; - } else { - parent->right = n->right; - } - } - - kfree(n); - t->size -= 1; - return 1; - } else { // children = 2, least simple - // Need to replace n's data with the smallest value in its right subtree - tree *right_subtree = new_tree(n->right); - node *min = min_node(right_subtree); - node *min_parent = min->parent; // Parent of min node - - n->data = min->data; // Move min node to where n was - - // Erase duplicate - if (min_parent->left == min) { - min_parent->left = NULL; - } else { - min_parent->right = min->right; - } - - kfree(min); - t->size -= 1; - return 1; - } -} - -// Support method for delete_tree -void delete(node *n) -{ - if (n != NULL) { - delete(n->left); - delete(n->right); - kfree(n); - } -} - -// Remove all node pointers and the tree pointer -void delete_tree(tree *t) -{ - if (t->root != NULL) - delete(t->root); - - kfree(t); -} - -// Returns 1 if the tree is empty, 0 otherwise -int is_empty(tree *t) -{ - return t->root == NULL ? 1 : 0; -} - -// Support method for print_tree -void print_nodes(node *n) -{ - printf("%d\n", *((int *)n->data)); - if (n->left != NULL) - print_nodes(n->left); - if (n->right != NULL) - print_nodes(n->right); -} - -// Print an in-order traversal of the tree -void print_tree(tree *t) -{ - node *root = t->root; - if (root != NULL) - print_nodes(root); -} diff --git a/kernel/data_structures/bitvector.c b/kernel/data_structures/bitvector.c deleted file mode 100644 index 5e23f289..00000000 --- a/kernel/data_structures/bitvector.c +++ /dev/null @@ -1,137 +0,0 @@ -#include -#include "klibc.h" -#include "data_structures/bitvector.h" - -uint32_t const WORD_SIZE = 32; - -/* return a pointer to a bit_vector struct of length size */ -bit_vector *make_vector(uint32_t size) { - // make the array - bit_vector *BV = (bit_vector*) kmalloc(sizeof(bit_vector)); - if((size % 32) == 0) { - uint32_t array[size >> 5]; - uint32_t x; - for(x = 0; (x < (size >> 5)); x++){ - array[x] = 0; - } - uint32_t *bit_vec = (uint32_t*) kmalloc(sizeof(array)); - BV->vector = bit_vec; - BV->length = size; - BV->actualLength = (size >> 5); - return BV; - } else { - uint32_t array[(size >> 5) + 1]; - uint32_t y; - for(y = 0; (y < ((size >> 5)+1)); y++){ - array[y] = 0; - } - uint32_t *bit_vec = (uint32_t*) kmalloc(sizeof(array)); - BV->vector = bit_vec; - BV->length = size; - BV->actualLength = (size >> 5) + 1; - return BV; - } -} - -/* return a whatever number, 1 or 0 is at position index */ -int32_t bv_get (uint32_t index, bit_vector* bit_vec) { - - if(index < bit_vec->length && index >= 0) { - - uint32_t val = (index >> 5); - uint32_t oneWord = bit_vec->vector[val]; - oneWord = oneWord >> (31 - (index % WORD_SIZE)); - uint32_t mask = 0x1; - return oneWord & mask; - } else {return -1;} // invalid index -} - -/* toggles the bit a position index */ -int32_t bv_toggle (uint32_t index, bit_vector* bit_vec) { - - if(index < bit_vec->length && index >= 0) { - - uint32_t val = (index >> 5); - uint32_t oneWord = bit_vec->vector[val]; - uint32_t mask = 0x1 << (31 - (index % WORD_SIZE)); - bit_vec->vector[val] = oneWord ^ mask; - return 1; - } else {return -1;} // invalid index -} - -/* puts a 1 at the position index */ -int32_t bv_set (uint32_t index, bit_vector* bit_vec) { - - if(index < bit_vec->length && index >= 0) { - - uint32_t val = (index >> 5); - uint32_t oneWord = bit_vec->vector[val]; - uint32_t mask = 0x1 << (31 - (index % WORD_SIZE)); - bit_vec->vector[val] = oneWord | mask; - return 1; - } else {return -1;} // invalid index -} - -/* puts a 0 at the position index */ -int32_t bv_lower (uint32_t index, bit_vector* bit_vec) { - - if(index < bit_vec->length && index >= 0) { - - uint32_t val = (index >> 5); - uint32_t oneWord = bit_vec->vector[val]; - uint32_t mask = ~(0x1 << (31 - (index % WORD_SIZE))); - bit_vec->vector[val] = oneWord & mask; - return 1; - } else {return -1;} // invalid index -} - -/* returns the first free index, if none are free return -1 */ -int32_t bv_firstFree (bit_vector* bit_vec) { - - uint32_t mask = 0x1; - uint32_t returner = 0; - uint32_t oneWord; - uint32_t x; - oneWord = bit_vec->vector[0]; - - for(x = 0; x < bit_vec->actualLength; x++) { - - uint32_t index = 0; - while(index < WORD_SIZE) { - - oneWord = bit_vec->vector[x]; - oneWord = (oneWord >> (31 - index)) & mask; - - if(!oneWord) { - return returner += index; - } - index++; - } returner += WORD_SIZE; - } - return -1; //no free spots -} - -/* returns whether the given index is free; 1 - true, 0 - false, -1 - invalid index*/ -int32_t bv_isfree(uint32_t index, bit_vector* bit_vec) -{ - uint32_t val; - uint32_t word; - if (index < bit_vec->length && index >= 0){ - val = (index >> 5); - word = bit_vec->vector[val]; - word = (word >> (31 - index)) & 0x1; - if (!word){ - return 1; - } - return 0; - } - return -1; -} - -/* free the bv from memory */ -int32_t bv_free (bit_vector* bit_vec) { - - kfree(bit_vec->vector); - kfree(bit_vec); - return 1; -} diff --git a/kernel/data_structures/hash_map.c b/kernel/data_structures/hash_map.c deleted file mode 100644 index b084ec04..00000000 --- a/kernel/data_structures/hash_map.c +++ /dev/null @@ -1,180 +0,0 @@ -#include "data_structures/hash_map.h" -#include "klibc.h" - -/* this should be prime */ -#define TABLE_STARTSIZE 1021 -#define ACTIVE 1 - -static unsigned long __hmap_is_prime(unsigned long val) { - int i, p, exp, a; - - for (i = 9; i--;) { - a = (rand() % (val - 4)) + 2; - p = 1; - exp = val - 1; - while (exp) { - if (exp & 1) { - p = (p * a) % val; - } - - a = (a * a) % val; - exp >>= 1; - } - - if (p != 1) { - return 0; - } - } - - return 1; -} - -static int __hmap_find_prime_greater_than(int val) { - if (val & 1) { - val += 2; - } else { - val++; - } - - while (!__hmap_is_prime(val)) { - val += 2; - } - - return val; -} - -static void __hmap_rehash(hmap_handle* hmap) { - long size = hmap->size; - hmap_entry* table = hmap->table; - - hmap->size = __hmap_find_prime_greater_than(size << 1); - hmap->table = (hmap_entry*) kmalloc(sizeof(hmap_entry) * hmap->size); - os_memset(hmap->table, 0, sizeof(hmap_entry) * hmap->size); - hmap->count = 0; - - while (--size >= 0) { - if (table[size].flags == ACTIVE) { - hmap_put(hmap, table[size].key, table[size].data); - } - } - - kfree(table); -} - -hmap_handle* hmap_create(){ - return hmap_create_fixed(TABLE_STARTSIZE); -}; - -hmap_handle* hmap_create_fixed(int startsize) { - hmap_handle* hmap = (hmap_handle*) kmalloc(sizeof(hmap_handle)); - - if (!startsize) { - startsize = TABLE_STARTSIZE; - } else { - startsize = __hmap_find_prime_greater_than(startsize - 2); - } - - hmap->table = (hmap_entry*) kmalloc(sizeof(hmap_entry) * startsize); - - os_memset(hmap->table, 0, startsize); - - hmap->size = startsize; - hmap->count = 0; - - return hmap; -} - -void hmap_put(hmap_handle* hmap, unsigned long key, const void* data) { - long index, i, step; - - if (hmap->size <= hmap->count) - __hmap_rehash(hmap); - - do { - index = key % hmap->size; - step = (key % (hmap->size - 2)) + 1; - - for (i = 0; i < hmap->size; i++) { - if (hmap->table[index].flags & ACTIVE) { - if (hmap->table[index].key == key) { - hmap->table[index].data = (void*) data; - return; - } - } else { - hmap->table[index].flags |= ACTIVE; - hmap->table[index].data = (void*) data; - hmap->table[index].key = key; - ++hmap->count; - return; - } - - index = (index + step) % hmap->size; - } - - /* it should not be possible that we EVER come this far, but unfortunately - not every generated prime number is prime (Carmichael numbers...) */ - __hmap_rehash(hmap); - } while (1); -} - -void* hmap_remove(hmap_handle* hmap, unsigned long key) { - long index, i, step; - - index = key % hmap->size; - step = (key % (hmap->size - 2)) + 1; - - for (i = 0; i < hmap->size; i++) { - if (hmap->table[index].data) { - if (hmap->table[index].key == key) { - if (hmap->table[index].flags & ACTIVE) { - hmap->table[index].flags &= ~ACTIVE; - --hmap->count; - return hmap->table[index].data; - } else { - /* in, but not active (i.e. deleted) */ - return 0; - } - } - } else { - /* found an empty place (can't be in) */ - return 0; - } - - index = (index + step) % hmap->size; - } - /* everything searched through, but not in */ - return 0; -} - -void* hmap_get(hmap_handle* hmap, unsigned long key) { - if (hmap->count) { - long index, i, step; - index = key % hmap->size; - step = (key % (hmap->size - 2)) + 1; - - for (i = 0; i < hmap->size; i++) { - if (hmap->table[index].key == key) { - if (hmap->table[index].flags & ACTIVE) { - return hmap->table[index].data; - } - break; - } else if (!hmap->table[index].data) { - break; - } - - index = (index + step) % hmap->size; - } - } - - return 0; -} - -long hmap_count(hmap_handle* hash) { - return hash->count; -} - -void hmap_free(hmap_handle* hash) { - kfree(hash->table); - kfree(hash); -} - diff --git a/kernel/data_structures/linked_list.c b/kernel/data_structures/linked_list.c deleted file mode 100644 index 492fc921..00000000 --- a/kernel/data_structures/linked_list.c +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************** - * linked_list.c - * - * Author: Brandon Olivier // any collaborators, please add name - * - * Date: 14 April 2014 - * - * Purpose: Provide basic linked list for CourseOS - * Implementation file - * - * TODO: Use locks or atomic operations to ensure that - * functions are safe - * - * - * - * - * - ********************************************************************/ - -#include "klibc.h" -#include "data_structures/linked_list.h" - -llist_node* llist_create_node(void *data) { - llist_node *node = (llist_node*) kmalloc(sizeof(llist_node)); - node->data = data; - return node; -} - -llist_handle* llist_create(void *data) { /* create more space than needed -- less resizing */ - llist_handle *result = (llist_handle *) kmalloc(sizeof(llist_node)); - result->count = 0; - llist_insert(result, llist_create_node(data), 0); - return result; -} - -void llist_enqueue(llist_handle * list, void * data) { - llist_insert(list, data, 0); -} - -void* llist_get_data(llist_handle *l, int index) { - return llist_get_node(l, index)->data; -} - -void* llist_dequeue(llist_handle * list) { - void * data = llist_get_data(list, 0); - llist_remove_at(list, 0); - return data; -} - -/* TODO: implmement free */ -void llist_free(llist_handle *l) { /* since free isn't really implemented, it's not going to do anything */ - llist_node *tmp = l->head; - llist_node *next = tmp->next; - while (tmp->next) { - kfree(tmp); - tmp = next; - next = tmp->next; - } - kfree(l); -} - -void llist_free_node(llist_node *node) { - kfree(node->data); - kfree(node); -} - -void llist_insert(llist_handle *l, void *data, int index) { - int i; - llist_node *next = l->head; - llist_node *prev; - l->count++; - for (i = 0; i < index; i++) { - prev = next; - next = next->next; - } - llist_node *new_node = llist_create_node(data); - prev->next = prev ? new_node : 0; - next->next = next ? new_node : 0; - if (l->tail->next) { - l->tail = l->tail->next; - } -} - -int llist_count(llist_handle *l) -{ - return l->count; -} - -void llist_remove_at(llist_handle *l, int index) { - llist_node *prev = llist_get_node(l, index); - llist_node *to_delete = prev->next; - prev->next = to_delete->next; - llist_free_node(to_delete); -} - - - -llist_node* llist_get_node(llist_handle *l, int index) { - int i; - llist_node *tmp = l->head; - for (i = 0; i < index; i++) { - tmp = tmp->next; - } - return tmp; -} - -void llist_set_data(llist_node *l, void *data) { - l->data = data; -} diff --git a/kernel/data_structures/priority_queue.c b/kernel/data_structures/priority_queue.c deleted file mode 100644 index 6a2118b2..00000000 --- a/kernel/data_structures/priority_queue.c +++ /dev/null @@ -1,156 +0,0 @@ -#include "klibc.h" -#include "data_structures/priority_queue.h" - -#define AMORITIZED_CONSTANT 2 -#define DEFAULT_COUNT 10 - -void __prq_shift_up(prq_handle * queue, int idx); -void __prq_shift_down(prq_handle * queue, int idx); - -void __prq_shift_up(prq_handle * queue, int idx) { - prq_node ** heap = queue->heap; - prq_node * node, *parent; - while (heap[idx]->priority < heap[idx / 2]->priority && idx > 1) { - node = heap[idx]; - parent = heap[idx / 2]; - parent->index = idx; - node->index = idx / 2; - heap[idx] = parent; - heap[idx / 2] = node; - idx /= 2; - } -} - -void __prq_shift_down(prq_handle * queue, int idx) { - int cidx; //index for child - prq_node ** heap = queue->heap; - prq_node * node, *child; - for (;;) { - cidx = idx * 2; - if (cidx > queue->count) { - break; //it has no child - } - if (cidx < queue->count) { - if (heap[cidx]->priority > heap[cidx + 1]->priority) { - ++cidx; - } - } - //swap if necessary - if (heap[cidx]->priority < heap[idx]->priority) { - node = heap[cidx]; - child = heap[idx]; - node->index = idx; - child->index = cidx; - heap[cidx] = child; - heap[idx] = node; - idx = cidx; - } else { - break; - } - } -} - -prq_node * prq_create_node() { - return kmalloc(sizeof(prq_node)); -} - -void prq_free_node(prq_node * node) { - if (node) { - kfree(node); - } -} - -prq_node * prq_peek(prq_handle * queue) { - if (queue) { - if (queue->count > 0) { - return queue->heap[1]; - } - } - - return 0; -} - -int prq_count(prq_handle * queue) { - if (queue) { - return queue->count; - } - - return 0; -} - -void __prq_amoritize(prq_handle * queue) { - int new_heap_size = queue->heap_size * AMORITIZED_CONSTANT; - prq_node** new_heap = (prq_node**) kmalloc( - sizeof(prq_node*) * new_heap_size); - os_memcpy((uint32_t *) queue->heap, (uint32_t *) new_heap, - (os_size_t) queue->heap_size * sizeof(prq_node*)); - kfree(queue->heap); - queue->heap = new_heap; - queue->heap_size = new_heap_size; -} - -void prq_enqueue(prq_handle * queue, prq_node * node) { - prq_node ** heap = queue->heap; - int index = (node->index = queue->count + 1); - heap[index] = node; - ++queue->count; - __prq_shift_up(queue, index); - if (queue->count + 1 == queue->heap_size) { - __prq_amoritize(queue); - } -} - -void prq_remove(prq_handle * queue, prq_node * node) { - if (!queue->count) { - return; - } - prq_node ** heap = queue->heap; - prq_node * end = heap[queue->count]; - int index = (end->index = node->index); - if (index == -1) { - return; - } - node->index = -1; - heap[index] = end; - heap[queue->count + 1] = 0; - --queue->count; - // FIXME optimize later - __prq_shift_up(queue, index); - __prq_shift_down(queue, index); -} - -prq_node * prq_dequeue(prq_handle * queue) { - if (!queue->count) { - return 0; - } - prq_node ** heap = queue->heap; - prq_node * top = heap[1]; - prq_node * end = heap[queue->count]; - end->index = 1; - top->index = -1; - heap[1] = end; - heap[queue->count] = 0; - --queue->count; - __prq_shift_down(queue, 1); - return top; -} - -prq_handle * prq_create_fixed(int n) { - n = MAX(1, n); - prq_handle * queue = (prq_handle*) kmalloc(sizeof(prq_handle)); - queue->count = 0; - queue->heap_size = n + 1; - queue->heap = (prq_node**) kmalloc(sizeof(prq_node*) * queue->heap_size); - return queue; -} - -prq_handle * prq_create() { - return prq_create_fixed(DEFAULT_COUNT); -} - -void prq_free(prq_handle * queue) { - if (queue) { - kfree(queue->heap); - kfree(queue); - } -} diff --git a/kernel/data_structures/ring_buffer.c b/kernel/data_structures/ring_buffer.c deleted file mode 100644 index c49eac1d..00000000 --- a/kernel/data_structures/ring_buffer.c +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************** - * ring_buffer.c - * - * Author: Brandon Olivier // any collaborators, please add name - * - * Date: 14 April 2014 - * - * Purpose: Provide ring buffer implementation for CourseOS - * - * TODO: Add locks or mutexes or something - * - ********************************************************************/ - -#include "ring_buffer.h" - -ring_buffer* create(int size) -{ - ring_buffer* rb = (ring_buffer *) malloc(sizeof(ring_buffer) * size); - rb->size_limit = size; - return rb; -} - -int put(ring_buffer *r, void *data) -{ /* do a size check */ - if(r->size >= r->size_limit) - return 0; // no space - r->size++; - rb_node* node = (rb_node *) malloc(sizeof(rb_node)); - node->data = data; - r->head->next = node; - r->head = node; - node->next = r->tail; - return 1; -} - -rb_node* get(ring_buffer *r) -{ - return r->tail; -} - -void clear(ring_buffer *r) -{ - rb_node* clear = r->tail; - r->tail = clear->next; - r->head->next = r->tail; - //free(clear->data); // nots sure if good idea - free(clear); -} - -ring_buffer* increase_size(ring_buffer *r, int by) -{ - int new_limit = r->size + by; - ring_buffer *new = (ring_buffer *) malloc(sizeof(ring_buffer) * new_limit); - new->size_limit = new_limit; - new->size = r->size; - new->tail = r->tail; - new->head = r->head; - free(r); - return new; -} diff --git a/kernel/data_structures/swap_pqueue.c b/kernel/data_structures/swap_pqueue.c deleted file mode 100644 index 8bd85b94..00000000 --- a/kernel/data_structures/swap_pqueue.c +++ /dev/null @@ -1,158 +0,0 @@ -#include -#include "swap_pqueue.h" -#include "swap_framework.h" -#include "klibc.h" - -void pqueue_init(struct swap_space *ss) -{ - head = (struct node*) kmalloc(sizeof(struct node)); - head->next = NULL; - head->e_head = ss->e_head; - head->lower_bits = ss->lower_bits; - head->priority = ss->priority; - head->store_func = ss->store_func; - head->retrieve_func = ss->retrieve_func; - path = head; - s = 1; -} - -void pqueue_push(struct swap_space *ss) -{ - struct node *restore = path; int count=1; - path = head; - while (count<=pqueue_size()) { - if (path->priority > ss->priority && count==1) { //set as new head - head = (struct node*) kmalloc(sizeof(struct node)); - head->next = path; - pqueue_set(head, ss); - path = restore; - break; - } - if (path->priority < ss->priority && path->next == NULL) { //set as new tail - path = restore; - path->next = (struct node*) kmalloc(sizeof(struct node)); - path = path->next; - pqueue_set(path, ss); - path->next = NULL; - break; - } - if (path->priority < ss->priority && count!=pqueue_size() && - (path->next)->priority > ss->priority) { //set in between nodes - struct node *temp = (struct node*) kmalloc(sizeof(struct node)); - pqueue_set(temp, ss); - temp->next = path->next; - path->next = temp; - path = restore; - break; - } - path = path->next; - count++; - } - s++; -} - -//set head to next node and delete previous node -//pops from front -void pqueue_pop_front() -{ - struct node *temp = head; - head = head->next; - kfree(temp); - s--; -} - -void pqueue_pop_back() -{ - kfree(path); - path = head; - while (path->next == NULL) { - path = path->next; - } - s--; -} - -void pqueue_pop_at(uint8_t ssid) -{ - struct node *temp = head; - int x; - for (x = 0; xlower_bits == ssid) { - break; - } - temp = temp->next; - } - if (x == 0) { - pqueue_pop_front(); - } else if (x == pqueue_size()-1) { - pqueue_pop_back(); - } else { - struct node *temp2 = head; - for (int y = 1; ynext; - } - temp2->next = temp->next; - kfree(temp); - } -} - -void pqueue_set(struct node *h, struct swap_space *ss){ - h->lower_bits = ss->lower_bits; - h->priority = ss->priority; - h->store_func = ss->store_func; - h->retrieve_func = ss->retrieve_func; - h->e_head = ss->e_head; -} - -struct node *pqueue_index(int i) -{ - if (i == 0) { - return head; - } - if (i == (pqueue_size()-1)) { - return path; - } - - struct node *restore = head; - int x; - for (x = 0; xnext; - } - - return restore; -} - -uint8_t pqueue_size() -{ - return s; -} - -// returns specified value from the head of list -void *pqueue_peek(int type) -{ - void *foo; - switch (type) { - case 0: - foo = &(head->lower_bits); - case 1: - foo = &(head->priority); - case 2: - foo = head->e_head; - } - return foo; -} - -struct node *pqueue_find(uint8_t ssid) -{ - struct node *temp = head; - - while (temp != NULL) { - if (temp->lower_bits == ssid) { - return temp; - } - temp = temp->next; - } - - return NULL; -} - - diff --git a/kernel/debug.sh b/kernel/debug.sh deleted file mode 100755 index 638978e2..00000000 --- a/kernel/debug.sh +++ /dev/null @@ -1 +0,0 @@ -../toolchain/arm-none-eabi/bin/arm-none-eabi-gdb diff --git a/kernel/drivers/clock.c b/kernel/drivers/clock.c deleted file mode 100644 index 59d0c96e..00000000 --- a/kernel/drivers/clock.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include "clock.h" - - -void get_time(){ - uint32_t temp_time = *CLOCK; - os_printf("the time is? %x\n", temp_time); - get_seconds(temp_time); - -} - -void get_seconds(uint32_t time_thing){ - uint32_t SECOND_MASK = 0xF; - uint32_t TENS_OF_SECONDS_MASK = 0x7; - uint32_t seconds = time_thing & SECOND_MASK; - uint32_t tens_seconds = (time_thing >> 4) & TENS_OF_SECONDS_MASK; - uint32_t total_seconds = seconds + 10 * tens_seconds; - os_printf("seconds: %d\n", total_seconds); - - -} diff --git a/kernel/drivers/mmci.c b/kernel/drivers/mmci.c deleted file mode 100644 index af4591a0..00000000 --- a/kernel/drivers/mmci.c +++ /dev/null @@ -1,359 +0,0 @@ -/** - * @file MMCI (Multimedia Card Interface) Driver - * - * @author Joseph Bourque, Matt Davidson, Weston Selleck \n - * QC and Support: Lane Kolbly - * - * @version 1.0 - * - * @section DESCRIPTION - * - * The driver for the SD card; provides an interface between the - * operating system and the SD card controller. Currently set up - * to use FIFO for input and output - * - * TODO: Need to implement DMA support at some time in the future - * (Not needed until multi-threading implemented) - * - * Completed On: 4/20/2015 Last Updated: 5/5/2015 - */ -#include "klibc.h" -#include "drivers/mmci.h" - -// MMCI Definitions - Used to access SD card registers; DO NOT CHANGE! -#define MMCI_BASE 0x10005000 -#define CMD 0x00C -#define DCTRL 0x02C -#define FIFO 0x080 -#define FIFO_CNT 0x048 -#define STATUS 0x34 -#define ARG 0x008 -#define CLR 0x038 -#define RESP_0 0x14 -#define RESP_1 0x18 -#define RESP_2 0x1C -#define RESP_3 0x20 -#define DATA_LEN 0x028 - -// bit shift definitions - Used to modify SD card registers; DO NOT CHANGE! -#define EXE (1 << 10) -#define RESP (1 << 6) -#define LRESP (1 << 7) -#define RCA_MASK 0xFFFF0000 -#define SET_WRITE 1 | (9 << 4) -#define SET_READ 3 | (9 << 4) -#define DISABLE 0x0 | (9 << 4) -#define READ_CNT (read_mmci(STATUS) & (1 << 21)) -#define WRITE_CNT (read_mmci(FIFO_CNT) > 0) -#define STATUS_ERR 0x3F - - - - - -/** - * Initialize SD Card Method - * - * Initializes SD card putting it in the transfer state; this should - * be called when the kernel boots up; readies the SD card for - * data transfer. Right now this function chooses the first available - * SD card. - * - * TODO: Add to/split up this function in order to work with multiple - * SD cards i.e. let the user set up additional SD cards past - * the first - * - * @return - * - * If the SD card was initialized correctly; this returns 0; otherwise - * this will return a negative integer value based on the value stored - * in the status register - */ - -int init_sd() -{ - asm volatile("cpsie if"); - int rca = 0; - - // let the SD card know you're about to call one of the ACMD commands - run_mmci(CMD, 55 | EXE); - - // Set up the argument register for the next command - run_mmci(ARG, 123); - - // Set & Execute the ACMD set voltage command - run_mmci(CMD, 41 | EXE); - - // Set & Execute the get card identifier command - run_mmci(CMD, 2 | EXE | RESP | LRESP); - - // Set & execute the obtain RCA command; this will allow you - // to identifiy and select a particular SD card to read/write - // to in the event you have more than one card - run_mmci(CMD, 3 | EXE | RESP); - - // obtain RCA address and mask out the status bits - rca = (read_mmci(RESP_0) & RCA_MASK); - - // Load masked RCA address into the argument register - run_mmci(ARG, rca); - - // Run the select card command and point it at the card loaded - // in the argument register - run_mmci(CMD, 7 | EXE | RESP); - - // Set the data length register to 512 to indicate the amount - // amount of data to be moved is 512 bytes - // Note: This sets the value of FIFO count as well - run_mmci(DATA_LEN, SD_BLOCK_SIZE); - - // Eventually print some status message here if the SD card - // failed to initialize properly but for now just print - // that it was loaded OK - os_printf("\nSD card ready for transfer\n"); - - return status(); -} - -/** - * SD Capacity Method - * - * Returns the maximum capacity of the SD card in bytes; for our - * current needs it computes the size statically - * - * TODO: Eventually this needs to be set up to calculate the size - * of the SD card dynamically to account for different sized - * SD cards - * - * @return Returns the size of the SD card (in bytes) - */ -uint32_t sd_capacity() -{ - return 128*1024*1024; -} - -/** - * Transmit to SD Card Method - * - * Writes the contents of the FIFO buffer to the SD card; Writes - * A single block at a time. - * - * @param - * - * void* buffer - Holds a single block of data and treats it as a - bitstream - * @param - * - * uint32_t address - Holds the address of the block of the SD card - * to write to; the address is a multiple of the - * block size - * @return - * - * If the write was successful this returns 0; otherwise - * this returns a negative integer based on the status - * flags set - */ -int sd_transmit(void* buffer, uint32_t address) -{ - //Set the block length on the SD card - run_mmci(ARG, SD_BLOCK_SIZE); - run_mmci(CMD, 16 | EXE | RESP); - - //Set up the write command - run_mmci(ARG, address); - run_mmci(CMD, 24 | EXE | RESP); - push_bytes(buffer); - - // Return that write succeeded for now - return status(); -} - -/** - * Receive from the SD Card Method - * - * Reads the contents of the FIFO buffer from the SD card; reads - * a single block at a time from the passed address and stores it - * in the passed buffer - * - * @param - * - * void* buffer - Serves a a recepticle to place the information - * read from disk - * @param - * - * uint32_t address - stores the address on disk to read from - * disk addresses are a mulitple of block - * size - * - * @return - * - * Returns 0 if the read was successful; otherwise returns a - * negative integer based on the value stored in the status - * register - */ -int sd_receive(void* buffer, uint32_t address) -{ - //Clear out FIFO and set to read - run_mmci(DCTRL, DISABLE); - run_mmci(DCTRL, SET_READ); - //Set address to read from & send the command to read - run_mmci(ARG, address); - run_mmci(CMD, 17 | EXE | RESP); - - pull_bytes(buffer); - - // Return that read succeeded for now - return status(); -} - -/** - * Clear Method - * - * Resets all non-dynamic status flags - * - * @return - * - * Returns 0 if the clear was successful; otherwise returns a negative - * integer based off the value stored in the status register - */ -int clear() -{ - // Return that the clear succeeded for now - // Clear all status flags - run_mmci(CLR, 0x2FF); - return status() ; -} - - -///// Helper Functions ///// Helper Functions ///// Helper Functions ///// - - -/** - * Push Bytes - * - * Helper method for the sd_transmit method; pushes bits into - * the fifo buffer using the passed buffer space - * - * @param - * - * void* buffer - An address which represents 1 block of data; - * provides a space for FIFO to interact with - * when writing to the SD card - * - * @return - * - * Returns 0 if the write was successful; otherwise returns a - * negative integer based on the value stored in the status - * register - */ -int push_bytes(void* buffer) -{ - //Clear out FIFO and set to write - run_mmci(DCTRL, DISABLE); - run_mmci(DCTRL, SET_WRITE); - int i = 0; - while(WRITE_CNT){ - run_mmci(FIFO, ((uint32_t*)buffer)[i]); - i++; - } - - // Return that the push succeeded for now - return status(); -} - -/** - * Pull Bytes Method - * - * Helper function for the sd_recieve method; pulls bits out of - * the FIFO buffer and stores them in the buffer passed into - * the function (buffer represents 1 block of data) - * - * @param - * - * void* buffer - An address in memory representing 1 block - * of data; provides a space for FIFO to store - * the result of the read from the SD card - * - * @return - * - * Returns 0 if the read was successful; otherwise returns a - * negative integer based on the value stored in the status - * register - */ -int pull_bytes(void* buffer) -{ - int i = 0; - while(READ_CNT){ - ((uint32_t*) buffer)[i] = read_mmci(FIFO); - i++; - } - - // Return that the pull succeeded for now - return status(); -} - -/** - * Run MMCI Method - * - * This method is primarily used to run the various mmci commands - * and it does so by using ARM assembly to store a value in register - * corresponding to an MMCI command - * - * @param - * - * uint32_t cmd - Stores the address offset based on the MMCI base - * address for a MMCI command. - * - * @param - * - * uint32_t args - Represents the bits which will actually be set - * on the register when running a specific command - */ -void run_mmci(uint32_t cmd, uint32_t args) -{ - uint32_t reg_address = MMCI_BASE+cmd; - asm volatile("str %0,[%1]" : : "r" (args), "r" (reg_address)); -} - -/** - * Read MMCI Method - * - * This method is primarily used for getting some response from a MMCI - * register (response register, status register, etc.) - * - * @param - * - * uint32_t target - Passes in the target register to read; represented - * as an offset to the MMCI base address - - * @return - * - * Returns the value stored in the target register as an integer value - */ -uint32_t read_mmci(uint32_t target) -{ - uint32_t response; - uint32_t reg_address = MMCI_BASE + target; - asm volatile("ldr %0,[%1]" : "=r" (response) : "r" (reg_address)); - return response; -} - -/** - * Status Method - * - * Helper method which handles error detection for the driver; because - * multiple bits can be set due to multiple errors; combine bits where - * neccessary to obtain error code - * - *@return - * - * if no error - will return 0 - * if -1 , error code 0 - * if -2 , error code 1 - * if -3 , error code 0 and 1 - */ -int status(){ -uint32_t stat = read_mmci(STATUS); -int error= stat & STATUS_ERR; -return (~error+1); -} diff --git a/kernel/drivers/timer.c b/kernel/drivers/timer.c deleted file mode 100644 index d9b1efcb..00000000 --- a/kernel/drivers/timer.c +++ /dev/null @@ -1,295 +0,0 @@ -/* Device Driver for ARM Dual-Timer Module (SP804) - Reference Manual can be found here : http://infocenter.arm.com/help/topic/com.arm.doc.ddi0271d/DDI0271.pdf*/ -//#include -#include "klibc.h" -#include "drivers/timer.h" -#include "interrupt.h" - -rasp_pi_timer *timer_pointers[4]; - -void timer_irq_handler(void* args); -void (*handlers[4])(void *args); - -/* initializes timers as an array. Call this before - * using any of the timer functions */ -void initialize_timers() -{ - os_printf("initializing timers\n"); - volatile rasp_pi_timer *TIMER_0 = (rasp_pi_timer *) 0x101e2000; - volatile rasp_pi_timer *TIMER_1 = (rasp_pi_timer *) 0x101e2020; - volatile rasp_pi_timer *TIMER_2 = (rasp_pi_timer *) 0x101e3000; - volatile rasp_pi_timer *TIMER_3 = (rasp_pi_timer *) 0x101e3020; - timer_pointers[0] = (rasp_pi_timer*) TIMER_0; - timer_pointers[1] = (rasp_pi_timer*) TIMER_1; - timer_pointers[2] = (rasp_pi_timer*) TIMER_2; - timer_pointers[3] = (rasp_pi_timer*) TIMER_3; - - handlers[0] = NULL; - handlers[1] = NULL; - handlers[2] = NULL; - handlers[3] = NULL; - - interrupt_handler_t *tmr_handler = kmalloc(sizeof(interrupt_handler_t)); - tmr_handler->handler = timer_irq_handler; - register_interrupt_handler(4, tmr_handler); -} - -#define CHECK_TIMER_INDEX(index) { if (index < 0 || index > 4) return -1; } - -/* This function sets the value that the timer will begin at. - * This operation also resets the timer to this new value. - * if you want to keep the timer running with its current state - * use set background load. */ -int set_load_value(int timer_index, int value) -{ - CHECK_TIMER_INDEX(timer_index); - - timer_pointers[timer_index]->timer_load_value = value; - return 0; -} - -//returns the current control register value (configuration of timer) -int get_timer_control_value(int timer_index) -{ - CHECK_TIMER_INDEX(timer_index); - - return timer_pointers[timer_index]->control; -} - -/* Sets the value for the timer to load the next time it reaches - * 0 and loads the reset value. Does not affect current timer. */ -int set_background_load_value(int timer_index, int value) -{ - CHECK_TIMER_INDEX(timer_index); - - timer_pointers[timer_index]->background_timer_load_value = value; - return 0; -} - -/* Clear any interrupt data for the timer. - * note: writing to the clear timer register clears - * the interrupt status completely. */ -int clear_interrupt(int timer_index) -{ - CHECK_TIMER_INDEX(timer_index); - - timer_pointers[timer_index]->interrupt_clear = 0x1; - - return 0; -} - -//enable 32 bit mode in the specified timer index -int set_32_bit_mode(int timer_index) -{ - CHECK_TIMER_INDEX(timer_index); - - disable_timer(timer_index); - timer_pointers[timer_index]->control |= 0x2; - return 0; -} - -int get_current_timer_value(int timer_index) -{ - CHECK_TIMER_INDEX(timer_index); - - return timer_pointers[timer_index]->timer_actual_value; -} - -//enable periodic mode of specified timer index -int set_periodic_mode(int timer_index) -{ - CHECK_TIMER_INDEX(timer_index); - - disable_timer(timer_index); - timer_pointers[timer_index]->control &= 0xFFFFFFBE; - - return 0; -} - -//converts ms into ticks -//assumes modes are valid, if not, should return 0 -int conversion(int timer_index, int milliseconds) -{ - int mode = (timer_pointers[timer_index]->control & 0xC) >> 2; - - int ticks = 0; - if (mode == 0) - { - ticks = 32; - } - else if (mode == 1) - { - ticks = 256; - } - else if (mode == 2) - { - ticks = 1000; - } - return milliseconds * ticks; -} - -//function to set timer to different timer clock rates... 0 -> 1 (default), 1 -> 16, 2 -> 256... -//any other modes are invalid and will do nothing -int set_prescale(int timer_index, int mode) -{ - CHECK_TIMER_INDEX(timer_index); - - disable_timer(timer_index); - if (mode == 0) - timer_pointers[timer_index]->control &= 0xFFFFFFF3; - else if (mode == 1) - { - timer_pointers[timer_index]->control |= 0x4; - timer_pointers[timer_index]->control &= 0xFFFFFFF7; - } - else if (mode == 2) - { - timer_pointers[timer_index]->control |= 0x8; - timer_pointers[timer_index]->control &= 0xFFFFFFFB; - } - return 0; -} - -//enables timer interrupt of the given timer index -int enable_timer_interrupt(int timer_index) -{ - CHECK_TIMER_INDEX(timer_index); - - timer_pointers[timer_index]->control |= (1 << 5); - return 0; -} - -//disables timer interrupt of the given timer index -int disable_timer_interrupt(int timer_index) -{ - CHECK_TIMER_INDEX(timer_index); - - timer_pointers[timer_index]->control &= 0xFFFFFFDF; - return 0; -} - -int set_free_running_mode(int timer_index) -{ - CHECK_TIMER_INDEX(timer_index); - - disable_timer(timer_index); - timer_pointers[timer_index]->control |= 0x1; - return 0; -} - -//starts the timer, countdown from load value -int enable_timer(int timer_index) -{ - CHECK_TIMER_INDEX(timer_index); - - timer_pointers[timer_index]->control |= (1 << 7); - return 0; -} - -//pauses the timer -int disable_timer(int timer_index) -{ - CHECK_TIMER_INDEX(timer_index); - - timer_pointers[timer_index]->control &= 0xFFFFFF7F; - return 0; -} - -//prints the configuration of the control byte -int print_control_status(int timer_index) -{ - CHECK_TIMER_INDEX(timer_index); - - os_printf("control byte:%x", timer_pointers[timer_index]->control); - return 0; -} - -/*starts interrupts every start_val ticks */ -//You give it a vallut and the specific timer you want to star. -// YOu have four timers just start with timer zero -// The speed of counter or number ticks depends on qemu hertz speed -// we don't know he start of it but it should be around 10 milliseconds -// per proccess. -// ex: start_timer_interrupts(0,10) which means start timer(0) -// and interrupt every 10 clicks. -int start_timer_interrupts(int timer_index, int milliseconds) -{ -// conversion(timer_index, milliseconds); - CHECK_TIMER_INDEX(timer_index); - - int clicks = conversion(timer_index, milliseconds); - - os_printf("CLICKS ARE %d\n", clicks); - - set_background_load_value(timer_index, clicks); - set_periodic_mode(timer_index); - enable_timer_interrupt(timer_index); - enable_timer(timer_index); - return 0; -} - -int register_handler(int timer_index, void (*handler)(void *args)) -{ - CHECK_TIMER_INDEX(timer_index); - handlers[timer_index] = handler; - return 0; -} - -int unregister_handler(int timer_index) -{ - CHECK_TIMER_INDEX(timer_index); - handlers[timer_index] = NULL; - return 0; -} - -void timer_irq_handler(void* args) -{ - clear_interrupt(0); - - os_printf("@@@@@@ RECEIVED TIMER INTERRUPT\n"); - - // TODO: find out which timer fired. For the moment, hard-code to 0 - if (handlers[0] != NULL) - { - handlers[0](args); - } -} - -void timer_test() -{ - -// enable_interrupt(ALL_INTERRUPT_MASK); - - /*interrupt_handler_t *tmr_handler = kmalloc(sizeof(interrupt_handler_t)); - tmr_handler->handler = simple_timer_handler; - os_printf("fn ptr: %X\n", simple_timer_handler); - register_interrupt_handler(4, tmr_handler);*/ - - os_printf("FIQ status: %X\n", mmio_read(VIC_FIQ_STATUS)); - initialize_timers(); - start_timer_interrupts(0, 10); - //print_control_status(1); - - // Wait forever... - /* os_printf("\n"); - int cnt = 0; - os_printf("Timer: %d\n", timer_pointers[0]->timer_actual_value); - os_printf("Timer: %d\n", timer_pointers[0]->timer_actual_value); - os_printf("Timer: %d\n", timer_pointers[0]->timer_actual_value); - while (!(timer_pointers[0]->masked_interrupt_status&1)) { - cnt++; - //os_printf("%X\n", timer_pointers[1]->timer_actual_value); - int i; - for (i=0; i<1000; i++); - } - os_printf("%d\n", cnt); - os_printf("%X\n", mmio_read(PIC_ADDRESS+0x8)); - os_printf("%X\n", mmio_read(VIC_IRQ_STATUS)); - os_printf("%X\n", mmio_read(VIC_FIQ_STATUS)); - os_printf("Timer: %d\n", timer_pointers[0]->timer_actual_value); - os_printf("Timer: %d\n", timer_pointers[0]->timer_actual_value); - os_printf("Timer: %d\n", timer_pointers[0]->timer_actual_value); - while(1); - */ - return; -} diff --git a/kernel/drivers/uart.c b/kernel/drivers/uart.c deleted file mode 100644 index 3ce28b3e..00000000 --- a/kernel/drivers/uart.c +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include "drivers/uart.h" -#include "mmap.h" - -void print_uart0(const char *s) -{ - while (*s != '\0') - { - mmio_write(UART0_ADDRESS, *s); - s++; - } -} - -void print_char_uart0(char c) -{ - mmio_write(UART0_ADDRESS, c); -} - -/* print the full 32 bits of a word at the given address */ -/* trailing newline... */ -void print_word_bits(uint32_t * c) -{ - int i; - for (i = 31; i >= 0; i--) - *c & (1 << i) ? print_uart0("1") : print_uart0("0"); - print_uart0("\n"); -} - -/* print the full 8-digit hex code of a word at the given address */ -/* no '0x' prefix, NO trailing newline */ -void print_word_hex(uint32_t * c) -{ - int i; - uint32_t a; - for (i = 0x7; i >= 0x0; i--) - { - a = *c & (0xf << (i * 0x4)); - a >>= (i * 0x4); - - if (a <= 9) - mmio_write(UART0_ADDRESS, (uint32_t )(a + (uint32_t )'0')); - else if (a <= 0xf) - mmio_write(UART0_ADDRESS, (uint32_t )((a - 0xa) + (uint32_t )'a')); - else - mmio_write(UART0_ADDRESS, (uint32_t )('?')); - } -} - -/* display memory at given address */ -/* format is: "[address]: word1 word2 word3\n", etc. */ -/* displays 30 words (10 lines) */ -void md(uint32_t * start) -{ - int i, j; - uint32_t *addr = start; - for (i = 0; i < 10; i++) - { - print_uart0("0x"); - print_word_hex((uint32_t *) &addr); - print_uart0(": "); - for (j = 0; j < 3; j++) - { - print_word_hex(addr); - print_uart0(" "); - addr++; - } - print_uart0("\n"); - } -} - -/*void print_uart0(const char *s) {*/ -/*while (uart->dd->uart0_inter_val == 0) {}*/ -/*if(uart.UARTCR & RXE > 0) */ -/*{*/ -/*while(*s != '\0') */ -/*{*/ -/**UART0 = (uint32_t)(*s);*/ -/*s++;*/ -/*}*/ -/*}*/ -/*}*/ - -/* We need to implement a lock here. klibc will be implementing the buffer - * we just need to ensure the FIFO isn't read out of order. - */ -/*char *read_uart0() */ -/*{*/ -/*uint32_t buffer[STD_IN_BUFFER_SIZE] = {0};*/ -/*while (uart->dd->uart0_inter_val == 0) {}*/ -/*uint32_t *iterator = buffer;*/ -/*do */ -/*{*/ -/*if(uart.UARTCR & TXE > 0) */ -/*{*/ -/*break;*/ -/*} */ -/*else */ -/*{*/ -/**iterator = uart.UARTDR;*/ -/*iterator++;*/ -/*}*/ -/*} while (*iterator != '\0');*/ -/*return buffer;*/ -/*}*/ - diff --git a/kernel/drivers/uart_pi.c b/kernel/drivers/uart_pi.c deleted file mode 100644 index 11d9464d..00000000 --- a/kernel/drivers/uart_pi.c +++ /dev/null @@ -1,151 +0,0 @@ -#include -#include "drivers/uart.h" -#include "mmap.h" - -#define UARTDR (UART0_ADDRESS_PI+0x00) // Data Register -#define UARTRSR (UART0_ADDRESS_PI+0x04) //Recieve status register -#define UARTFR (UART0_ADDRESS_PI+0x18) // Flag Register -#define UARTILPR (UART0_ADDRESS_PI+0x20) //IrDA low power counter register -#define UARTIBRD (UART0_ADDRESS_PI+0x24) // Integer baud rate -#define UARTFBRD (UART0_ADDRESS_PI+0x28) //Fractional baud rate register -#define UARTLCR_H (UART0_ADDRESS_PI+0x2C) // Line control register -#define UARTCR (UART0_ADDRESS_PI+0x30) //Control Register -#define UARTIFLS (UART0_ADDRESS_PI+0x34) // Interrupt FIFO level select register -#define UARTIMSC (UART0_ADDRESS_PI+0x38) //Interrupt mask set/clear register -#define UARTRIS (UART0_ADDRESS_PI+0x3C) //Raw interrupt status register -#define UARTMIS (UART0_ADDRESS_PI+0x40) //masked interrupt status register -#define UARTICR (UART0_ADDRESS_PI+0x44) // Interrupt clear register -#define UARTDMACR (UART0_ADDRESS_PI+0x48) // DMA controlled register -#define GPPUD (GPIO_ADDRESS_PI + 0x94) //Controls pull up/down on GPIO pins -#define GPPUDCLK0 (GPIO_ADDRESS_PI + 0x98) //GPIO Clock - - -void init_uart() -{ - //Disable UART - mmio_write(UARTCR, 0x00000000); - - mmio_write(GPPUD, 0x00000000); - for(int i = 0;i<150;i++){ - asm volatile ("nop"); - } - - mmio_write(GPPUDCLK0, (1<<14) | (1<<15)); - for(int i = 0;i<150;i++){ - asm volatile ("nop"); - } - - mmio_write(GPPUDCLK0,0x00000000); - - mmio_write(UARTICR, 0x7FF); - //Enable DMA memory reads & writes with UART - //mmio_write(UARTDMACR, (1<<0) | (1<<1)); - - //Enable FIFO and set word length to 8 - mmio_write(UARTLCR_H, (1<<4) | (1<<5) | (1<<6)); - //Set the baud transfer rate at 115200 - mmio_write(UARTIBRD, 1); - mmio_write(UARTFBRD, 40); - - //Enable interrupts - mmio_write(UARTIMSC, (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10)); - //Enable UART and UART transfer - mmio_write(UARTCR, (1<<0) | (1<<8)); -} - -void print_char_uart0(char c) { - //Wait for room in the FIFO queue - while(mmio_read(UARTFR) & (1<<5)) {} - mmio_write(UART0_ADDRESS_PI, c); //Changed -} - -void print_uart0(const char *s) { - while(*s != '\0') { - while(mmio_read(UARTFR) & (1<<5)) {} - - print_char_uart0(*s); //Altering for testing purposes, don't kill me! - s++; - } -} - - - -/* print the full 32 bits of a word at the given address */ -/* trailing newline... */ -void print_word_bits(uint32_t * c) { - int i; - for(i = 31; i >= 0; i--) - *c & (1 << i) ? print_uart0("1") : print_uart0("0"); - print_uart0("\n"); -} - -/* print the full 8-digit hex code of a word at the given address */ -/* no '0x' prefix, NO trailing newline */ -void print_word_hex(uint32_t * c){ - int i; - uint32_t a; - for(i = 0x7; i >= 0x0; i--){ - a = *c & (0xf << (i*0x4)); - a >>= (i*0x4); - while(mmio_read(UARTFR) & (1<<5)) {} - if(a <= 9) - mmio_write(UART0_ADDRESS_PI, (uint32_t)(a + (uint32_t )'0')); //Changed - else if(a <= 0xf) - mmio_write(UART0_ADDRESS_PI, (uint32_t)((a - 0xa) + (uint32_t )'a'));//Changed - else - mmio_write(UART0_ADDRESS_PI, (uint32_t)('?')); //Changed - } -} - -/* display memory at given address */ -/* format is: "[address]: word1 word2 word3\n", etc. */ -/* displays 30 words (10 lines) */ -void md(uint32_t * start){ - int i, j; - uint32_t *addr = start; - for(i = 0; i < 10; i++) { - print_uart0("0x"); print_word_hex((uint32_t *)&addr); print_uart0(": "); - for(j = 0; j < 3; j++) { - print_word_hex(addr); - print_uart0(" "); - addr++; - } - print_uart0("\n"); - } -} - -/*void print_uart0(const char *s) {*/ -/*while (uart->dd->uart0_inter_val == 0) {}*/ -/*if(uart.UARTCR & RXE > 0) */ -/*{*/ -/*while(*s != '\0') */ -/*{*/ -/**UART0 = (uint32_t)(*s);*/ -/*s++;*/ -/*}*/ -/*}*/ -/*}*/ - -/* We need to implement a lock here. klibc will be implementing the buffer - * we just need to ensure the FIFO isn't read out of order. - */ -/*char *read_uart0() */ -/*{*/ -/*uint32_t buffer[STD_IN_BUFFER_SIZE] = {0};*/ -/*while (uart->dd->uart0_inter_val == 0) {}*/ -/*uint32_t *iterator = buffer;*/ -/*do */ -/*{*/ -/*if(uart.UARTCR & TXE > 0) */ -/*{*/ -/*break;*/ -/*} */ -/*else */ -/*{*/ -/**iterator = uart.UARTDR;*/ -/*iterator++;*/ -/*}*/ -/*} while (*iterator != '\0');*/ -/*return buffer;*/ -/*}*/ - diff --git a/kernel/elf.c b/kernel/elf.c deleted file mode 100644 index 8038efe6..00000000 --- a/kernel/elf.c +++ /dev/null @@ -1,259 +0,0 @@ -/* Worked on by Jeremy Wenzel, Kaelen Haag, and Sam Allen */ -#include "elf.h" -#include "klibc.h" -#include // Probably going to be removed - -unsigned char* filePointer; -unsigned char* startPointer; -//OVERHAUL TO MAKE EVERYTHING PASSED BY REFERENCE RATHER THAN VALUE. -//I THINK WE SHOULD JUST COMMENT OUT ALL THE SECTION HEADER STUFF BECAUSE IT'S NOT USED AND WILL BE A PAINTO MESS WITH. NEED TO MAKE PROGRAM HEADER ARRAY PASS BY VALUE AND NEED TO FIX get_value to take in refernce rather than value. DO TONIGHT OR TOMORROW - KAELEN - -/* Gets the value of the bytes on a big endian system */ -uint32_t do_big_endian(uint32_t size) -{ - uint32_t value = 0; - while (size > 0) - { - value = value << 8; - value = value + *filePointer; - filePointer++; - size--; - } - return value; -} - -/* Gets the value of the bytes on a little endian system */ -uint32_t do_little_endian(uint32_t size) -{ - uint32_t value = 0; - uint32_t num = 0; - int i = 0; - while (i < size) - { - num = *filePointer; - num = num << (8 * i); - value = value + num; - filePointer++; - i++; - } - return value; - -} - -/* Gets value of bytes given a size of bytes */ -//Make this pass by reference -uint32_t get_value(uint32_t size, Elf_Ehdr *h) -{ - if (h->e_ident[EI_DATA] == 1) - return do_little_endian(size); - else - return do_big_endian(size); -} - -/* Checks if the file is even an elf file */ -/* Returns 1 if elf file, -1 if not */ -int32_t isElf(Elf_Ehdr *h) -{ - // checks if elf file - char ELFMAG0 = get_value(1, h);// 0x7f - char ELFMAG1 = get_value(1, h);// 'E' - char ELFMAG2 = get_value(1, h);// 'L' - char ELFMAG3 = get_value(1, h);// 'F' - if (ELFMAG0 != 127 || ELFMAG1 != 'E' || ELFMAG2 != 'L' || ELFMAG3 != 'F') - return -1; - h->e_ident[EI_MAG0] = ELFMAG1; - h->e_ident[EI_MAG1] = ELFMAG2; - h->e_ident[EI_MAG2] = ELFMAG3; - return 1; -} - -/* Parses elf header of ELF file and places into ELF struct header */ -/* CRITICAL: It is important to initialize the elf header before - sending it into the function. Makes sure no data is lost */ -int32_t read_elf_header(Elf_Ehdr *h, unsigned char *pointer) -{ - filePointer = startPointer = pointer; - int32_t check = isElf(h); - if (check == -1) - { - return -1; - } - //os_printf("Size of char: %d\n", sizeof(char)); - //os_printf("Size of get_value(1, h): %d\n", sizeof((char)get_value(1, h))); - char temp = get_value(1, h); - //os_printf("Size of temp: %d\n", sizeof(temp)); - h->e_ident[EI_CLASS] = temp; // get_value(1, h); // get class - - temp = get_value(1, h); - h->e_ident[EI_DATA] = temp; //get_value(1, h); // endian - - temp = get_value(1, h); - h->e_ident[EI_VERSION] = temp; //get_value(1, h); // original version of ELF - - temp = get_value(1, h); - h->e_ident[EI_OSABI] = temp; //get_value(1, h); // Target operating system ABI - - temp = get_value(1, h); - h->e_ident[EI_ABIVERSION] = temp; //get_value(1, h); // Don't really know? - - int32_t skip = 0; // skips the padding - while (skip < 7) - { - get_value(1, h); - skip++; - } - Elf_Half half_temp = get_value(2, h); - h->e_type = half_temp; //get_value(2, h); // get type of file - - half_temp = get_value(2, h); - h->e_machine = half_temp; //get_value(2, h); // gets machine type (should be arm in our case) - - Elf_Word word_temp = get_value(4, h); - h->e_version = word_temp; //get_value(4, h); // version number (should be 1) - if (h->e_ident[EI_CLASS] == 1) // get entry point - { - word_temp = get_value(4, h); - h->e_entry = word_temp; //get_value(4, h); - } - else - h->e_entry = get_value(8, h); - - if (h->e_ident[EI_CLASS] == 1) // get program header offset - { - word_temp = get_value(4, h); - h->e_phoff = word_temp; //get_value(4, h); - } - else - h->e_phoff = get_value(8, h); - - if (h->e_ident[EI_CLASS] == 1) // get section header offset - { - word_temp = get_value(4, h); - h->e_shoff = word_temp; //get_value(4, h); - } - else - h->e_shoff = get_value(8, h); - - word_temp = get_value(4, h); - h->e_flags = word_temp; //get_value(4, h); // get flag number - - half_temp = get_value(2, h); - h->e_ehsize = half_temp; //get_value(2, h); // get elf header size - - half_temp = get_value(2, h); - h->e_phentsize = half_temp; //get_value(2, h); // get program header size - - half_temp = get_value(2, h); - h->e_phnum = half_temp; //get_value(2, h); // number of program headers - - half_temp = get_value(2, h); - h->e_shentsize = half_temp; //get_value(2, h); // section header size - - half_temp = get_value(2, h); - h->e_shnum = half_temp; //get_value(2, h); // number of section headers - - half_temp = get_value(2, h); - h->e_shstrndx = half_temp; //get_value(2, h); // section header string table index - - return 1; // return success -} - -void read_program_header_table(Elf_Ehdr *eh, Elf_Phdr ph[], - unsigned char *pointer) -{ - filePointer = startPointer = pointer; - filePointer = startPointer + eh->e_phoff; - int i = 0; - Elf_Word word_temp = 0; - while (i < eh->e_phnum) - { - word_temp = get_value(4, eh); - ph[i].p_type = word_temp; //get_value(4, eh); - ph[i].p_offset = get_value(4, eh); - ph[i].p_vaddr = get_value(4, eh); - ph[i].p_paddr = get_value(4, eh); - ph[i].p_filesz = get_value(4, eh); - ph[i].p_memsz = get_value(4, eh); - ph[i].p_flags = get_value(4, eh); - ph[i].p_align = get_value(4, eh); - i++; - } - -} - -/* Reads the section header table and places it into the the section header array */ -/* CRITICAL: The section header must be initalized with the correct size, - before put into the function */ -void read_section_header_table(Elf_Ehdr *eh, Elf_Shdr sh[], uint32_t *pointer) -{ - filePointer = startPointer = (unsigned char*) pointer; - int i = 0; - filePointer = startPointer + eh->e_shoff; - while (i < eh->e_shnum) - { - sh[i].sh_name = get_value(4, eh);// get name, which is index into string table - sh[i].sh_type = get_value(4, eh); // type of section header - sh[i].sh_flags = get_value(4, eh); // flags that partain to the header - sh[i].sh_addr = get_value(4, eh);// address of header (don't know much yet) - sh[i].sh_offset = get_value(4, eh); // offset from beginning of elf file - sh[i].sh_size = get_value(4, eh); // size of this section - sh[i].sh_link = get_value(4, eh); // link (don't know much yet) - sh[i].sh_info = get_value(4, eh); // info (don't know much yet) - sh[i].sh_addralign = get_value(4, eh);// address aligned (don't know much yet) - sh[i].sh_entsize = get_value(4, eh); - i++; - } -} - -/* Goes to the Section header that contains the section header string table */ -/* It then analyzes the table and puts them into each section header */ -/* This makes it easier to differentiate between sections when put into loader */ -void parse_section_header_names(Elf_Ehdr *eh, Elf_Shdr sh[], uint32_t *pointer) -{ - filePointer = startPointer = (unsigned char*) pointer; - filePointer = startPointer + sh[eh->e_shstrndx].sh_offset;// This pointer iterates through the section header - int i = 1; - - filePointer++; - while (i < eh->e_shnum) - { - if (os_strcmp(((char*) filePointer), ".symtab") == 0) - { // checks if symbol table - sh[i].sh_numname = SYMTAB; - } - else if (os_strcmp(((char*) filePointer), ".text") == 0) - { // checks if .text table - sh[i].sh_numname = TEXT; - } - else if (os_strcmp(((char*) filePointer), ".comment") == 0) - { // checks if comment table - sh[i].sh_numname = COMMENT; - } - else if (os_strcmp(((char*) filePointer), ".strtab") == 0) - { // checks if string table - sh[i].sh_numname = STRTAB; - } - else if (os_strcmp(((char*) filePointer), ".shstrtab") == 0) - { // checks if section header string table - sh[i].sh_numname = SHSTRTAB; - } - else if (os_strcmp(((char*) filePointer), ".rodata") == 0) - { // checks if read only data - sh[i].sh_numname = RODATA; - } - else if (os_strcmp(((char*) filePointer), ".data") == 0) - { // checks if initialized data - sh[i].sh_numname = DATA; - } - else if (os_strcmp(((char*) filePointer), ".bss") == 0) - { // checks if unitialized data - sh[i].sh_numname = BSS; - } - else - ; - while (*((char*) filePointer) != '\0')// move on to next sting in the list - filePointer++; - filePointer++; - i++; // move on to next item in section header table - } -} diff --git a/kernel/fs/cmdline/Documents b/kernel/fs/cmdline/Documents deleted file mode 100644 index f8955934..00000000 --- a/kernel/fs/cmdline/Documents +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef __FILE_H__ -#define __FILE_H__ - - -#include "bitvector.h" -#include - -#define BLOCKSIZE 512 -#define MAX_NAME_LENGTH 32 -#define MAX_DATABLOCKS_PER_INODE 68 -#define DIR_ENTRY_SIZE 40 -#define MAX_NUM_INDIRECT_BLOCKS 50 -#define MAX_DATABLOCKS_PER_INDIRECT_BLOCK ((BLOCKSIZE/4)-2) -#define MAX_DIR_ENTRIES_PER_DATA_BLOCK ((int)((BLOCKSIZE-4)/DIR_ENTRY_SIZE)-2) - -//IMPORTANT!! --------------------------------------------------------------------------------------------------- -//all constants are in units of block NUMBER | -//the indexes of arrays are also in units of block NUMBER relative to the starting offset of their cathegory. | -//--------------------------------------------------------------------------------------------------------------- - -//constants of file system, that wil be filled at boot time -struct superblock -{ - // char* fs_name; // 32 bytes (max length for this field abides by MAX_NAME_LENGTH) - int fs_version; // 36 bytes - int magic_num; // 40 bytes - int sd_card_capacity; // 44 bytes - int block_size; // 48 bytes - int root_inum; // 52 bytes - int max_inodes; // 56 bytes - int inode_size; - int max_data_blocks; // 66 bytes - int inode_bitmap_loc; // 70 bytes - int data_bitmap_loc; // 74 bytes - // int indirect_blocks_bitmap_loc; // - int start_inode_table_loc; // 78 bytes - int start_data_blocks_loc; // 82 bytes, start_inode_table_loc + 200 b/c 200 inode bl - // int start_indirect_block_table_loc; // - // int max_indirect_blocks; - // char spaceholder[???]; Might need this to make the cast from memory to superblock work...not sure??? Don't think we need this, but not sure - // the rest of the superblock will be empty for now (BLOCKSIZE - 82 = 512 - 82 = 430 free/wasted bytes) -}; - -//metadata of each file or directory -struct inode { - int inum; //inum of the file (4bytes) - int fd_refs; //how many times the file is referenced (=appears in the opentable) (4bytes) - int size; // size of the whole file (4 bytes) - int is_dir; // 1 if this is a directory, 0 if this is a file (4 bytes) - int usr_id; // id of the user who created the file (4 bytes) ...not yet used! - int direct_blocks_in_file; // how many direct block are being used (4 bytes) - int data_blocks[MAX_DATABLOCKS_PER_INODE]; // array of data (now long 68) - int indirect_blocks_in_file; // how many indirect block are being used (4 bytes) - int indirect_blocks[MAX_NUM_INDIRECT_BLOCKS]; // 50*4 = 200 bytes ....50 indirect blocks right now - bit_vector* perms; // permissions of the file (12 bytes) -}; - -struct indirect_block // total size is 1 block -{ - int block_num; - int blocks_in_file; //blocks actually used - int data_blocks[MAX_DATABLOCKS_PER_INDIRECT_BLOCK]; // because this is just an array of ints, so it's BLOCKSIZE/4 bytes bc each int is 4 bytes -}; - -struct dir_entry -{ - int inum; - int name_length; //including null terminating string - char name[MAX_NAME_LENGTH]; // 32 chars right now -}; // 8 _ MAX_NAME_LENGTH bytes long...40 bytes right now - -struct dir_data_block -{ - int block_num; - int num_entries; - struct dir_entry dir_entries[MAX_DIR_ENTRIES_PER_DATA_BLOCK]; -}; - -struct data_block -{ - char data[BLOCKSIZE]; -}; - -struct dir_helper //used by helper functions in file.c -{ - int dir_levels; - char* truncated_path; - char* last; -}; - -struct stats //statistics about the file -{ - int size; //size of the file - int fd_refs; //how many times it is open now - int is_dir; //is this a directory -}; - -int kopen(char* filepath, char mode); //opens the file of filepath with permissions mode -int kread(int fd, void* buf, int numBytes); //reads the open file corresponding to fd -int kwrite(int fd, void* buf, int num_bytes); //writes the open file corresponding to fd -int kclose(int fd); //closes the cpen file corresponding to fd -int kseek(int fd, int num_bytes); //moves the offset of the open file fd -int kdelete(char* filepath); //deletes the file or directory following filepath -int kcreate(char* filepath, char mode, int is_this_a_dir); //creates and opens a file or directory with permissions mode in fielpath -int kcopy(char* source, char* dest, char mode); //copies the contents of a file -int kls(char* filepath); //shows contents of one directory -int kfs_init(int inode_table_cache_size, int data_block_table_cache_size, int reformat); -int kfs_shutdown(); - -// // ------------------------------------------------------------------------------------------------------------------------------------------------------- -// /* HELPER FUNCTIONS */ - -//from the index, gets the corresponding indirect block, either from cache or from disk -void get_indirect_block(int index, struct indirect_block* cur_indirect_block); - -//from the inum, gets corresponding inode, either from cache or disk -void get_inode(int inum, struct inode* result_inode); - -//gets the inum of nextpath (file or dir) looking at the direct data blocks of cur_inode -int get_inum_from_direct_data_block(struct inode* cur_inode, char * next_path); - -//gets the inum of netxpath (file or dir) looking at the indirect data blocks of cur_inode -int get_inum_from_indirect_data_block(struct inode * cur_inode, char * next_path); - -//finds the inode (will be result_inode) following filepath, going dir_levels down the path, starting from starting_inum -int kfind_inode(char* filepath, int starting_inum, int dir_levels, struct inode* result_inode); - -//finds the name of the directory path (result->truncated_path) and the name of the ending part (result->last) and the number of levels (result->levels) -//result has to be kmalloc-ed by and kfree-d by whoever calls this functinos. Also remember to free last and truncated_path. -void kfind_dir(char* filepath, struct dir_helper* result); - -//transmits or receives the data block bitvector or the inode bitvecotr to and from disk -// First parameter: TRANSMIT or RECEIVE (defined) -// Second paramter: put pointer to bitvector (example: data_block_bitmap for data, inode_bitmap for inodes) -// Third parameter: put where that bitvecotr starts in memory (example: FS->data_bitmap_loc for data, FS->inode_bitmap_loc for inode) -// Fourth parameter: how many there are (example: FS->max_data_blocks for data, FS->max_inodes for inodes) -// index = index you would put in the bitvector -// all = 0 for only one index, 1 for all the bitvector -int transmit_receive_bitmap(int t_or_r, bit_vector* vec, int starting_loc, int max, int bit_index, int all); - -/* Helper function to add a new dir_entry to a directory file and optinally write it out to disk. - Updates the last data block of the cur_inode (directory) to add a dir_entry that stores the mapping of the new inode to its inum */ -int add_dir_entry(struct inode* cur_inode, int free_inode_loc, struct dir_helper* result); - -int get_block_address(struct inode *file_inode, int block_num); - -// Helper function for kread(): -int read_partial_block(struct inode *c_inode, int offset, void* buf_offset, int bytes_left, void* transfer_space); - -// Helper function for kread(): -int read_full_block(struct inode *c_inode, int offset, void* buf_offset, int bytesLeft, void* transfer_space);; - -int read_inode(struct inode *c_inode, int offset, void* buf, int num_bytes); - -struct stats * get_stats(char * filepath, struct stats * result); - - -#endif - diff --git a/kernel/fs/cmdline/Makefile b/kernel/fs/cmdline/Makefile deleted file mode 100755 index ee1f4b8e..00000000 --- a/kernel/fs/cmdline/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -INCLUDES+=-Iinclude - -CC?=gcc - -CFLAGS+=-O0 -CFLAGS+=-g -CFLAGS+=-D__HOST - -OBJS+=file.o -OBJS+=fakelibs.o -OBJS+=open_table.o -OBJS+=bitvector.o -OBJS+=main.o - -PROG:=buildfs - -all: $(PROG) - -$(PROG): $(OBJS) - $(CC) $(CFLAGS) $(OBJS) -o $(PROG) - -file.o: ../fat16/file.c - $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ - -bitvector.o: ../../data_structures/bitvector.c - $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ - -open_table.o: ../open_table.c - $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ - -%.o: %.c - $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ - -card.sd: - dd if=/dev/zero of=card.sd conv=notrunc bs=512 count=250000 - -clean: - rm -f $(OBJS) - rm -f $(PROG) diff --git a/kernel/fs/cmdline/fakelibs.c b/kernel/fs/cmdline/fakelibs.c deleted file mode 100644 index 5594d094..00000000 --- a/kernel/fs/cmdline/fakelibs.c +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include -#include - -/* Memory management */ - -void *kmalloc(unsigned int len) -{ - return malloc(len); -} - -void kfree(void *ptr) -{ - free(ptr); -} - -/* klibc functions */ - -// GAH src is the 1st argument. -void *os_memcpy(void *src, void *dst, int len) -{ - return memcpy(dst, src, len); -} - -void *os_memset(void *ptr, char c, int len) -{ - return memset(ptr, c, len); -} - -int os_strcmp(char *s1, char *s2) -{ - return strcmp(s1, s2); -} - -char *os_strcpy(char *s1, char *s2) -{ - return strcpy(s1, s2); -} - -int os_strlen(char *s) -{ - return strlen(s); -} - -/* SD card */ - -int init_sd() -{ - // Noop - return 0; -} - -int sd_transmit(void *data, uint32_t addr) -{ - FILE *f = fopen("card.sd", "r+"); - fseek(f, addr, SEEK_SET); - fwrite(data, 1, 512, f); - fclose(f); - return 0; -} - -int sd_receive(void *data, uint32_t addr) -{ - FILE *f = fopen("card.sd", "r+"); - fseek(f, addr, SEEK_SET); - fread(data, 1, 512, f); - fclose(f); - return 0; -} diff --git a/kernel/fs/cmdline/include/data_structures/bitvector.h b/kernel/fs/cmdline/include/data_structures/bitvector.h deleted file mode 120000 index e4561579..00000000 --- a/kernel/fs/cmdline/include/data_structures/bitvector.h +++ /dev/null @@ -1 +0,0 @@ -../../../../include/data_structures/bitvector.h \ No newline at end of file diff --git a/kernel/fs/cmdline/include/data_structures/linked_list.h b/kernel/fs/cmdline/include/data_structures/linked_list.h deleted file mode 120000 index 38507f21..00000000 --- a/kernel/fs/cmdline/include/data_structures/linked_list.h +++ /dev/null @@ -1 +0,0 @@ -../../../../include/data_structures/linked_list.h \ No newline at end of file diff --git a/kernel/fs/cmdline/include/drivers/mmci.h b/kernel/fs/cmdline/include/drivers/mmci.h deleted file mode 120000 index 2a88fac5..00000000 --- a/kernel/fs/cmdline/include/drivers/mmci.h +++ /dev/null @@ -1 +0,0 @@ -../../../../include/drivers/mmci.h \ No newline at end of file diff --git a/kernel/fs/cmdline/include/fs b/kernel/fs/cmdline/include/fs deleted file mode 120000 index 52616344..00000000 --- a/kernel/fs/cmdline/include/fs +++ /dev/null @@ -1 +0,0 @@ -../../../include/fs \ No newline at end of file diff --git a/kernel/fs/cmdline/include/global_defs.h b/kernel/fs/cmdline/include/global_defs.h deleted file mode 120000 index 9e8e79ca..00000000 --- a/kernel/fs/cmdline/include/global_defs.h +++ /dev/null @@ -1 +0,0 @@ -../../../include/global_defs.h \ No newline at end of file diff --git a/kernel/fs/cmdline/include/klibc.h b/kernel/fs/cmdline/include/klibc.h deleted file mode 120000 index bc34e179..00000000 --- a/kernel/fs/cmdline/include/klibc.h +++ /dev/null @@ -1 +0,0 @@ -../../../include/klibc.h \ No newline at end of file diff --git a/kernel/fs/cmdline/main.c b/kernel/fs/cmdline/main.c deleted file mode 100644 index 0d627e03..00000000 --- a/kernel/fs/cmdline/main.c +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @file - * - * Build FS (Bootstraps the File System) - * - * @author Lane Kolbly, Ginevra Gaudioso - * @version 1.0 - * - * @section NOTE ON CMDLINE FOLDER - * SD card gets run automatically in the makefile, however - * the .h files in the cmdline folder need to be manually updated and - * are independent of the files in the include folder - * > e.g. if someone changes include/file.h then fs/cmdline/file.h - * needs to be updated - * - * - * @section DESCRIPTION - * - * Takes a directory and creates an SD card image from - * it - * - */ -#include "fs/file.h" -#include -#include -#include -#include - -#define BUF_SIZE 4096 -#define MAX_FILE_NAME_LEN 1024 - -/** - * Adds a specific file to the card.sd image - * - * Adds the file at the path specified by filename to the SD card - * image indicated by dst_filename - * - * @param - * - * char *src_file_name - holds the path to the file to add to the SD - * card image - * - * @param - * - * char *dst_file_name - holds the path to the SD card image to - * add the file to - */ -void addFile(const char *src_file_name, const char *dst_file_name) -{ - FILE *f = fopen(src_file_name, "r"); - assert(f); - - // FIXME: should all be const char* - kclose(kcreate((char*) dst_file_name, 'r', 0)); - int fd = kopen((char*) dst_file_name, 'w'); - - char buf[BUF_SIZE]; - int nread; - - while ((nread = fread(buf, 1, BUF_SIZE, f)) > 0) - { - kwrite(fd, buf, nread); - //printf("\t\t%d bytes\n", nread); - } - - kclose(fd); - fclose(f); -} - -int main(int argc, char **argv) -{ - int fd; - int i; - int l; - DIR *dir; - struct dirent *entry; - - char src_file[MAX_FILE_NAME_LEN]; - char dst_file[MAX_FILE_NAME_LEN]; - - kfs_init(0, 0, 1); - - for (i = 1; i < argc; i++) - { - dir = opendir(argv[i]); - if (dir == NULL) - { - printf("Could not find directory %s\n", argv[i]); - printf("SAD :(\n"); - return -1; - } - printf("In %s\n", argv[i]); - - while ((entry = readdir(dir))) - { - if (entry->d_name[0] == '.') - continue; // skip - - l = snprintf(src_file, MAX_FILE_NAME_LEN, "%s/%s", argv[i], entry->d_name); - assert(l < MAX_FILE_NAME_LEN); - l = snprintf(dst_file, MAX_FILE_NAME_LEN, "/%s", entry->d_name); - assert(l < MAX_FILE_NAME_LEN); - - printf("\tAdding %s to %s ...\n", src_file, dst_file); - - addFile(src_file, dst_file); - } - - closedir(dir); - } - - return 0; -} diff --git a/kernel/fs/fat16/file.c b/kernel/fs/fat16/file.c deleted file mode 100644 index 8bb6d31b..00000000 --- a/kernel/fs/fat16/file.c +++ /dev/null @@ -1,2237 +0,0 @@ -/** - * @file - * - * Course OS FS - * - * @author - * - * Joel Iventosh, Ginevra Gaudioso, Weston Sellek, Charlie Cox - * Matt Davidson, Joseph Bourque - * - * @version 1.0 - * - * @section DESCRIPTION - * - * Course OS FS is a custom file system (started out as FAT 16 but changed into this). - * The file system uses a superblock to initialize the file system as well as the SD card - * on boot. Data blocks are stored as array of integers that indexes into the corresponding - * block number on the SD card (note: some blocks are reserved, data blocks use an offset to - * access blocks on the SD card) DO NOT FORGET TO ADD OFFSET TO BLOCK NUMBERS!; Each file or - * directory is stored with an inode which contains metadata about the file as well as the - * list of addresses on disk where the data the file holds is stored. Directories are indicated - * with the is_dir flag and data blocks for directories are dir_entry structs; - * Each file has 100 direct blocks and 20 indirect blocks; no methods are - * currently implemented to keep data contiguous. - * - * CURRENTLY WORKING - * - Have working directories and directory hierarchy - * - Standardized error codes; defined in header file - * - Open file table working - * - Create working - * - Open working - * - Close working - * - Read working - * - Write working - * - * TO FIX - * - Max number of files per directory currently limited to 700 due to error finding - * and opening files; you can technically create more, but open will not find them - * - indirect blocks do not seem to work - * - ls, delete, and copy are untested; could work, but might not; TEST BEFORE USING! - * - permissions - * - */ -#include -#include "klibc.h" -#include "data_structures/bitvector.h" -#include "fs/open_table.h" -#include "fs/file.h" -#include "drivers/mmci.h" - -#define TRANSMIT 0 -#define RECEIVE 1 - -//CONSTANTS: -const int SUPERBLOCK = 1; -// const int MAX_NAME_LENGTH = 32; moved this to a define -int MAX_BLOCKS; -// const int INODE_SIZE = 128; shouldn't need this...should be able to do sizeof(Inode) -int MAX_MEMORY; -int INODE_TABLE_CACHE_SIZE; -int NUM_INODE_TABLE_BLOCKS_TO_CACHE; -int INDIRECT_BLOCK_TABLE_CACHE_SIZE; -int NUM_INDIRECT_BLOCK_TABLE_BLOCKS_TO_CACHE; -int INODES_PER_BLOCK = 1; -int DATA_BLOCK_TABLE_CACHE_SIZE; -int NUM_DATA_BLOCK_TABLE_BLOCKS_TO_CACHE; - - -struct superblock* FS; -bit_vector* inode_bitmap; -bit_vector* data_block_bitmap; - -struct inode** inode_table_cache; //is this right? we want an array of inode pointers... -struct indirect_block** indirect_block_table_cache; // an array of pointers to indirect_blocks -struct inode** inode_table_temp; -struct data_block** data_block_table_cache; -// void* data_table; not sure what this is or why we had/needed/wanted it... - -/** - * Format the SD card for Course OS FS - * - * Creates the super block & metadata for the file system, creates the - * root directory of the file system and writes the first block on the - * SD card as empty. - * - */ -int kfs_format() -{ - os_printf("In kfs_format\n"); - // Lay down the superblock to block 1 - struct superblock sblock; - sblock.fs_version = 1; - sblock.magic_num = 0xDEADBEAF; - sblock.sd_card_capacity = 128000000; - sblock.block_size = BLOCKSIZE; - sblock.root_inum = 0; - sblock.max_inodes = 4000; - sblock.inode_size = BLOCKSIZE; - sblock.max_data_blocks = 200000; - sblock.inode_bitmap_loc = 10; - sblock.data_bitmap_loc = 50; - sblock.start_inode_table_loc = 1000; - sblock.start_data_blocks_loc = 50000; - - void *block = kmalloc(BLOCKSIZE); - os_memset(block, 0, BLOCKSIZE); - os_memcpy((uint32_t*)&sblock, block, sizeof(struct superblock)); - sd_transmit(block, 1*BLOCKSIZE); - - // Lay down the root inode - struct inode root_inode; - root_inode.inum = 0; // Isn't this redundant? - root_inode.fd_refs = 0; - root_inode.size = 0; - root_inode.is_dir = 1; - root_inode.usr_id = 0; - root_inode.direct_blocks_in_file = 1; - // root_inode.data_blocks[0] = sblock.start_data_blocks_loc; - root_inode.data_blocks[0] = 0; - root_inode.indirect_blocks_in_file = 0; - os_memset(block, 0, BLOCKSIZE); - os_memcpy((uint32_t*)&root_inode, block, sizeof(struct inode)); - sd_transmit(block, sblock.start_inode_table_loc*BLOCKSIZE); - - // Lay down the first (empty...) data block for the directory. - struct dir_data_block ddb; - ddb.block_num = 0; - ddb.num_entries = 0; - os_memset(block, 0, BLOCKSIZE); - os_memcpy((uint32_t*)&ddb, block, sizeof(struct dir_data_block)); - sd_transmit(block, sblock.start_data_blocks_loc*BLOCKSIZE); - - // Update the inode bitmap - /*unsigned char i = 0x80; - os_memset(block, 0, BLOCKSIZE); - os_memcpy(&i, block, 1); - sd_transmit(block, sblock.inode_bitmap_loc*BLOCKSIZE);*/ - kfree(block); - return SUCCESS; -} - -/** - * Load file system into memory and initialize the SD card - * - * Initializes the SD card to set it up for data transfer, once the SD card - * is initialized metadata for the file system is loaded into memory and used - * to obtain the free list table and data block table. - * - * @param - * - * int inode_table_cache_size - no longer needed; should be removed - * - * @param - * - * int data_block_table_cache_size - no longer needed; should be removed - * - * @param - * - * int reformat - if this is set to a non-zero value; this formats the file - * system before initialization; if set to 0; initialization occurs with no - * format - * - * @return - * - * Returns 0 if initialization was successful; does not do any error checking - * or reporting at current; will need to be added in at some point in the future - */ -int kfs_init(int inode_table_cache_size, int data_block_table_cache_size, int reformat){ - - INODE_TABLE_CACHE_SIZE = inode_table_cache_size; - DATA_BLOCK_TABLE_CACHE_SIZE = data_block_table_cache_size; - // TODO: Reading the root inode has weird issues (getting is_dir==0) with inode table block cache. - NUM_INODE_TABLE_BLOCKS_TO_CACHE = 0;//((int) INODE_TABLE_CACHE_SIZE/BLOCKSIZE) + 1; - NUM_DATA_BLOCK_TABLE_BLOCKS_TO_CACHE = 0;//((int) DATA_BLOCK_TABLE_CACHE_SIZE/BLOCKSIZE) + 1; - - //initialize the SD Card driver: - if(!init_sd()){ - //initiallized successfully: - os_printf("SD Card initiallized successfully!!!\n"); - }else{ - os_printf("FATAL ERROR!!!!! SD Card NOT initialized successfully!\n"); - //handle errors returned by SD Card...will implement this later... - }//end else - - // Bootstrap the FS... - if (reformat) { - kfs_format(); - } - - //read in the super block from disk and store in memory: - FS = (struct superblock*) kmalloc(BLOCKSIZE); - sd_receive((void*)FS, (SUPERBLOCK*BLOCKSIZE)); // make all blocks addresses, like here - - INODES_PER_BLOCK = (FS->block_size/FS->inode_size); - - //initialize the free list by grabbing it from the SD Card: - inode_bitmap = make_vector(FS->max_inodes); - data_block_bitmap = make_vector(FS->max_data_blocks); - - //HACK...shouldn't need to do this, but do, so leave for now - int m; - for(m = 0; m < FS->max_inodes; m++){ - bv_lower(m, inode_bitmap); - } //end HACK...shouldn't need to do this, but do, so leave for now - - bv_set(0, inode_bitmap); - bv_set(0, data_block_bitmap); - - - // initilize the inode_table_cache in memory: - inode_table_temp = (struct inode**)kmalloc(NUM_INODE_TABLE_BLOCKS_TO_CACHE * BLOCKSIZE); - inode_table_cache = (struct inode**) kmalloc((sizeof(struct inode*))* FS->max_inodes); - int i; - for(i = 0; i < FS->max_inodes; i++){ - if(i < NUM_INODE_TABLE_BLOCKS_TO_CACHE * INODES_PER_BLOCK){ - if(i % INODES_PER_BLOCK == 0){ - sd_receive((((void*)inode_table_temp) + ((i/INODES_PER_BLOCK)*BLOCKSIZE)), (FS->start_inode_table_loc + (i/INODES_PER_BLOCK)) * BLOCKSIZE); - } - inode_table_cache[i] = (struct inode*)((inode_table_temp + (((int)(i/INODES_PER_BLOCK))*BLOCKSIZE)) + ((i % INODES_PER_BLOCK)*FS->inode_size)); - } - //each iteration through the loop will grab 1 inodes, since we can fit 1 inodes per block - else{ - inode_table_cache[i] = NULL; - } - }//end for - // inode_table_cache = (inode*) inode_table_temp; // cast the void pointer to an Inode pointer - - // initilize the data_block_table_cache in memory: - void* data_block_table_temp = (void*) kmalloc(NUM_DATA_BLOCK_TABLE_BLOCKS_TO_CACHE * BLOCKSIZE); - data_block_table_cache = (struct data_block**) kmalloc((sizeof(struct data_block*))* FS->max_data_blocks); - for(i = 0; i < FS->max_data_blocks; i++){ - if(i < NUM_DATA_BLOCK_TABLE_BLOCKS_TO_CACHE){ - sd_receive(data_block_table_temp + (i*BLOCKSIZE), (FS->start_data_blocks_loc) + (i*BLOCKSIZE)); - data_block_table_cache[i] = (struct data_block*)(data_block_table_temp + (i*BLOCKSIZE)); - } else{ - data_block_table_cache[i] = NULL; - } - }//end for - - fs_table_init(); //initializes open_table stuff - - os_printf("Finished initializing table...\n"); - return SUCCESS; -}//end fs_init() function - -/** - * Removes the file system from memory - * - * Writes the filesystem metadata, the free block table and the data block table to disk - * for persistant storage and then frees all memory which was being used to allocate those - * resources - * - * @return - * - * Returns 0 if shutdown successfully loaded everything out of memory; no error handling or - * recording is currently implemented; this needs to be implemented in the future so that - * shutdown does not occur if this is called in the middle of a read or write - */ -int kfs_shutdown(){ - int i; - //TODO: write inodes pointed to by inode_table_cache back to disk to ensure it's up to date: - - //TODO: write indirect_blocks pointed to by data_block_table_cache back to disk to ensure it's up to date: - transmit_receive_bitmap(TRANSMIT, inode_bitmap, FS->inode_bitmap_loc, FS->max_inodes, 0, 1); //transmit inode bitmap - transmit_receive_bitmap(TRANSMIT, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, 0, 1); //transmit block bitmap - - //free inodes stored in inode_table_cache: - for(i = 0; i < NUM_INODE_TABLE_BLOCKS_TO_CACHE; i++){ - if(inode_table_cache[i] != NULL){ - kfree(inode_table_cache[i]); - }//end if - }//end for - - //free inode_table_cache itself: - kfree(inode_table_cache); - - //free indirect_blocks stored in data_block_table_cache: - for(i = 0; i < NUM_DATA_BLOCK_TABLE_BLOCKS_TO_CACHE; i++){ - if(data_block_table_cache[i] != NULL){ - kfree(data_block_table_cache[i]); - }//end if - }//end for - - //free data_block_table_cache itself: - kfree(data_block_table_cache); - kfree(inode_table_temp); - //TODO: free anything else that needs to be freed... - - fs_table_shutdown(); //frees open_table stuff - return SUCCESS; -}//end kfs_shutdown() function - - -// ------------------------------------------------------------------------------------------------------------------------------------------------------- -/* HELPER FUNCTIONS */ - -/** - * Retrieves an indirect data block from the SD card - * - * Retrieves the specified indirect data block from the SD card using the passed index - * and then sets it as the current indirect block - * - * @param - * - * struct inode* cur_inode - points to the file which we want to read the indirect block - * index from - * - * @param - * - * int index - holds an index which corresponds to a location in the data block table - * - * @param - * - * struct indirect_block* cur_indirect_block - Holds the address of the current indirect - * block - * - */ -void get_indirect_block(struct inode* cur_inode, int index, struct indirect_block* cur_indirect_block) { - // indirect_block is not in the cache table, so get it from disk: - if(cur_inode->indirect_blocks_in_file <= 0){ - transmit_receive_bitmap(RECEIVE, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, 0, 1); - int new_indirect_block_loc = bv_firstFree(data_block_bitmap); - bv_set(new_indirect_block_loc, data_block_bitmap); - cur_inode->indirect_blocks[0] = new_indirect_block_loc; - cur_inode->indirect_blocks_in_file++; - transmit_receive_bitmap(TRANSMIT, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, new_indirect_block_loc, 0); - sd_transmit((void*) cur_inode, (cur_inode->inum + FS->start_inode_table_loc) * BLOCKSIZE); - os_memset(cur_indirect_block, 0, BLOCKSIZE); - cur_indirect_block->block_num = new_indirect_block_loc; - cur_indirect_block->blocks_in_file = 0; - }//end if - sd_receive((void*) cur_indirect_block, (index + FS->start_data_blocks_loc)*BLOCKSIZE); // the firs -}//end get_indirect_block - -/** - * gets corresponding inode, from the SD card - * - * Retrieves an inode from the SD card using specified inum storing - * it into a specified address. - * - * @param - * - * int inum - corresponds to a location in the inode table i.e. it is an - * index to a location in the inode table - * - * @param - * - * inode* result_inode - holds a specified address to store the retrieved - * inode at - * - */ -//from the inum, gets corresponding inode, either from cache or disk -void get_inode(int inum, struct inode* result_inode){ - // if(inode_table_cache[inum] != NULL){ - // // the inode is in the inode_cache_table, so get it: - // result_inode = (inode_table_cache[inum]); - // }else{ - // inode is not in the cache table, so get it from disk: - // // struct inode* inode_spaceholder = (void*) kmalloc(BLOCKSIZE); - // sd_receive((void*)inode_spaceholder, ((inum/INODES_PER_BLOCK)+FS->start_inode_table_loc)*BLOCKSIZE); // the firs - // struct inode *block_of_inodes = inode_spaceholder; - // result_inode = block_of_inodes[inum % INODES_PER_BLOCK]; - // kfree(inode_spaceholder); - // need to implement an eviction policy/function to update the inode_table_cache... - // this will function w/o it, but should be implemented for optimization - // }//end if else - sd_receive(result_inode, (inum + FS->start_inode_table_loc)*BLOCKSIZE); -}//end get_inode() helper function - -/** - * gets the inum of nextpath (file or dir) looking at the direct data blocks of cur_inode - * - * Uses the current file's inode in order to retrieve the nested directory's inode - * and then return it - * - * @param - * - * struct inode* cur_inode - holds the inode for the current data block - * - * @param - * - * char * next_path - the path you are searching - * - * @return - * - * Returns the inode of a specific nested directory; at this time there is no error checking - * or reporting on this function; needs to be added in at a later data - */ -int get_inum_from_direct_data_block(struct inode* cur_inode, const char * next_path){ - int inum = -1; - int i; - int file_found = 0; // initialize to false (i.e. file not found) - struct dir_data_block* cur_data_block = (struct dir_data_block*) kmalloc(BLOCKSIZE); - - for(i = 0; i < cur_inode->direct_blocks_in_file; i++){ - sd_receive(cur_data_block, (cur_inode->data_blocks[i] + FS->start_data_blocks_loc)*BLOCKSIZE); - - int j; - for(j = 0; j < (cur_data_block->num_entries); j++){ - struct dir_entry file_dir = cur_data_block->dir_entries[j]; - if(!os_strcmp(file_dir.name, next_path)){ - file_found = 1; //we found the file, so break out of loop - inum = file_dir.inum; - break; - } - if(file_found){ - break; - } - }//inner for - if(file_found){ - break; - } - }//outer for - kfree(cur_data_block); - return inum; -}//end get_inum_from_direct_data_block() helper helper function - -/** - * Returns the index to an inode by searching through an indirect block - * - * gets the inum of netxpath (file or dir) looking at the indirect - * data blocks of cur_inode - * - * @param - * - * struct inode* cur_inode - holds the inode for the current data block - * - * @param - * - * char * next_path - the path you are searching - * - * @return - * - * Returns the inode of a specific nested directory; at this time there is no error checking - * or reporting on this function; needs to be added in at a later data -*/ -int get_inum_from_indirect_data_block(struct inode * cur_inode, const char * next_path) { - int i; - int inum = -1; - int cur_indirect_block_num = -1; - int file_found = 0; // initialize to false (i.e. file not found) - struct indirect_block cur_indirect_block; - for(i = 0; i < cur_inode->indirect_blocks_in_file; i++){ - cur_indirect_block_num = cur_inode->indirect_blocks[i]; - - get_indirect_block(cur_inode, cur_indirect_block_num, &cur_indirect_block); - - void* dir_spaceholder = (void*) kmalloc(BLOCKSIZE); - int j; - int num_indirect_blocks = cur_inode->indirect_blocks_in_file; - for(j = 0; j < num_indirect_blocks; j++){ - sd_receive(dir_spaceholder, (cur_indirect_block.data_blocks[j])*BLOCKSIZE); - struct dir_data_block cur_data_block = *((struct dir_data_block*) dir_spaceholder); - int k; - for(k = 0; k < (cur_data_block.num_entries); k++){ - struct dir_entry file_dir = cur_data_block.dir_entries[k]; // - if(!os_strcmp(file_dir.name, next_path)){ - file_found = 1; //we found the file, so break out of loop - inum = file_dir.inum; - break; - } - }//inner for - if(file_found){ - break; - } - }//outer for - kfree(dir_spaceholder); - if(file_found){ - break; - } - }//end for - return inum; -}//end of get_inum_from_indirect_data_block - -/** - * locates an inode using the file path and store it in the result_inode - * - * finds the inode (will be result_inode) following filepath, going - * dir_levels down the path, starting from starting_inum - * - * @param - * - * char* filepath - holds the filepath leading to the inode - * - * @param - * - * int dir_levels - holds the number of directories the inode is nested - * under - * - * @param - * - * struct inode* result_inode - Used to hold the inode once it has been - * located - * - * @return - * - * Returns 0 if inode was successfully located and stored; otherwise - * returns -1 - */ -int kfind_inode(const char* filepath, int starting_inum, int dir_levels, struct inode* result_inode) { //filepath and starting inum must correspond... - int current_inum = starting_inum; - - int a = 0; - for(a = 0; a < dir_levels-1; a++) { - int k = 1; - // int k = 0; - char next_path[MAX_NAME_LENGTH] = {0}; - - //get path of next inode - while ((filepath[k] != '/') && (k <= MAX_NAME_LENGTH) && (filepath[k] != '\0')) { - next_path[k-1] = filepath[k]; - k++; - }//end of litte while to find next_path - - filepath += k; - - // Store inode with current_inum current_inum in result_inode - get_inode(current_inum, result_inode); - - current_inum = get_inum_from_direct_data_block(result_inode, next_path); - - if(current_inum < 0){ - //current_inum not found in any direct blocks of result_inode - //look for it in the indirect blocks now - current_inum = get_inum_from_indirect_data_block(result_inode, next_path); - } - - if(current_inum < 0){ - //next_path not found in current_inode - os_printf("404 ERROR! File not found.\nPlease ensure full filepath is specified starting from root (/)\n"); - return ERR_404; //file not found - } - }//outer most for loop - //current_inum of target inode found, store that inode in result_inode - - get_inode(current_inum, result_inode); - - return SUCCESS; -}//end kfind_inode() helper function - -/** - * Uses the file path to obtain information about a directory and stores it in result - * - * finds the name of the directory path (result->truncated_path) and the name of the - * ending part (result->last) and the number of levels (result->levels) result has to - * be kmalloc-ed by and kfree-d by whoever calls this functinos. Also remember to free - * last and truncated_path. - * - * @param Description of method's or function's input parameter - * @param ... - * @return Description of the return value - */ -void kfind_dir(const char* filepath, struct dir_helper* result){ - int dir_levels = 0; - int total_chars = 0; - char* iterator = (char*) filepath; //root still level 0, so start from what's next - int index = 0; - while(index < MAX_NAME_LENGTH){ - if(iterator[0] == '\0'){ - //index++; - break; - } - else if(iterator[0] == '/'){ - dir_levels++; - index = 0; - }else{ - index++; - } - iterator++; - total_chars++; - }//end while - total_chars -= index; - - char* truncated_path = (char*)kmalloc(total_chars+1); // do we need to kmalloc this? - char* last = (char*)kmalloc(index+1); - int i; - for(i = 0; i < total_chars; i++){ - truncated_path[i] = filepath[i]; - } - truncated_path[i] = 0; - for (i=0; idir_levels = dir_levels; - result->truncated_path = truncated_path; - result->last = last; - return; //caller of function is responsible for freeing memory for truncated_path and filepath -}//end kfind_dir() function - -/** - * Used to transmit a block to disk or recieve a block from disk - * - * transmits or receives the data block bitvector or the inode bitvecotr to and from disk - * - * @param - * - * int t_or_r - Determines whether operation is a TRANSMIT (0) to disk or a RECIEVE (1) - * from disk - * - * @param - * - * bit_vector* vec - Pointer to a bitvector (either a data_block_bitmap for data or an - * inode_bitmap for inodes) - * - * @param - * - * int starting_loc - holds the location where the bit vector starts in memory - * - * @param - * - * int max - holds the number of blocks to write to disk - * - * @param - * - * int all - Determines whether to only write 1 index (0) or whether to write the entire - * bit vector (1) to disk - * - * @return - * - * Return 0 if the transmission/recieval was successful; otherwise returns an error code - */ -int transmit_receive_bitmap(int t_or_r, bit_vector* vec, int starting_loc, int max, int bit_index, int all){ - int error = 0; - int num_blocks = (max/(8 * BLOCKSIZE)) + 1; - if (t_or_r != TRANSMIT || t_or_r != RECEIVE) { - return ERR_INVALID; - } - if(all){ //transmit or receive all the bitvector - int i; - for(i = 0; i < num_blocks; i++){ - if (t_or_r == TRANSMIT) { - error = sd_transmit((void*) (vec->vector + (i*BLOCKSIZE)), (starting_loc + i)*BLOCKSIZE); - } - else { //receive - error = sd_receive((void*) (vec->vector + (i*BLOCKSIZE)), (starting_loc + i)*BLOCKSIZE); - } - if(error < 0){ - os_printf("ERROR! Failed to transmit or receive\n"); - return error; - } - } - }else{ //transmit or reveive only the block corresponding to the index - int block_to_change = (bit_index/8)/BLOCKSIZE; - if (t_or_r == TRANSMIT) { - error = sd_transmit((void*) (vec->vector + (block_to_change*BLOCKSIZE)), (starting_loc + block_to_change)*BLOCKSIZE); - } - else { //receive - error = sd_receive((void*) (vec->vector + (block_to_change*BLOCKSIZE)), (starting_loc + block_to_change)*BLOCKSIZE); - } - if(error < 0){ - os_printf("ERROR! Failed to transmit or receive\n"); - return error; - } - } - return error; -}//end transmit_receive_bitmap helper function - - -/** - * Adds a new file to an existing directory - * - * Helper function to add a new dir_entry to a directory file and - * optinally write it out to disk. Updates the last data block of - * the cur_inode (directory) to add a dir_entry that stores the - * mapping of the new inode to its inum - * - * @param - * - * struct inode* cur_inode - holds the inode for the current data block - * - * @param - * - * int free_inode_loc - points to a location in the free inode table - * - * @param - * - * struct dir_helper* result - holds information about the directory you - * are trying to add to - * - * @return - * - * Returns 0 if the file was added successfully; otherwise returns an error - */ -int add_dir_entry(struct inode* cur_inode, int free_inode_loc, struct dir_helper* result){ - - int flag_free_cur_indirect_block = 0; - - //first get the appropriate data block, either from the array of direct data blocks from an indirect block: - struct dir_data_block* dir_block = (struct dir_data_block*) kmalloc(BLOCKSIZE); - struct indirect_block* cur_indirect_block; - //if the cur_inode's array of direct data blocks has not reached max capacity, grab the last data block in the array to update: - if((cur_inode->direct_blocks_in_file <= MAX_DATABLOCKS_PER_INODE) && (cur_inode->indirect_blocks_in_file == 0)) { - sd_receive((void*) dir_block, (cur_inode->data_blocks[(cur_inode->direct_blocks_in_file)-1] + FS->start_data_blocks_loc)*BLOCKSIZE); - }else{ - //all the direct data blocks are full, so grab the last indirect block in the array of indirect blocks: - cur_indirect_block = (struct indirect_block*) kmalloc(BLOCKSIZE); - get_indirect_block(cur_inode, (cur_inode->indirect_blocks_in_file - 1), cur_indirect_block); - sd_receive((void*) dir_block, (cur_indirect_block->data_blocks[(cur_indirect_block->blocks_in_file)-1] + FS->start_data_blocks_loc)*BLOCKSIZE); - flag_free_cur_indirect_block = 1; - // kfree(cur_indirect_block); - } - /* dir_block is now a direct data block that holds the content of the last data block in the file - either from cur_inode's array of direct data blocks or from its last indirect data block */ - - //create the new dir_entry and populate it's fields: - struct dir_entry new_dir_entry; - new_dir_entry.inum = free_inode_loc; - os_strcpy(new_dir_entry.name, result->last); - new_dir_entry.name_length = os_strlen(result->last); - - //check to see if the data block we recieved above has room to add a new dir_entry to it; if not, create a new data block, if possible: - if(dir_block->num_entries < MAX_DIR_ENTRIES_PER_DATA_BLOCK){ - //the data block has room to add the new dir_entry, so we add it: - dir_block->dir_entries[dir_block->num_entries] = new_dir_entry; - dir_block->num_entries++; - cur_inode->size += sizeof(struct dir_entry); - - sd_transmit((void*) dir_block, (dir_block->block_num + FS->start_data_blocks_loc) * BLOCKSIZE); - }else{ - /* the data block doesn't have room to add the new dir_entry, so we need to add a new data block.... - either by adding: (1) as a direct data block, - (2) to the current indirect block or - (3) add a new indirect block then add a new data block to that */ - //first kmalloc space for a new_dir_block: - int new_data_block_loc = bv_firstFree(data_block_bitmap); //Consult the data_block_bitmap to find a free block to add the new data block at - if(new_data_block_loc < 0){//disk is full - os_printf("ERROR! Disk full\n"); - kfree(dir_block); - if (cur_indirect_block != NULL) { - kfree(cur_indirect_block); - } - return ERR_FULL; - } - bv_set(new_data_block_loc, data_block_bitmap); - struct dir_data_block* new_dir_block = (struct dir_data_block*) kmalloc(BLOCKSIZE); - - new_dir_block->num_entries = 0; - new_dir_block->block_num = new_data_block_loc; - - if(cur_inode->direct_blocks_in_file < MAX_DATABLOCKS_PER_INODE){ - //Case (1): add a direct data block to cur_inode: - cur_inode->data_blocks[cur_inode->direct_blocks_in_file] = new_dir_block->block_num; - cur_inode->direct_blocks_in_file++; - - new_dir_block->dir_entries[new_dir_block->num_entries] = new_dir_entry; - new_dir_block->num_entries++; - cur_inode->size += sizeof(struct dir_entry); - sd_transmit((void*) new_dir_block, (new_dir_block->block_num + FS->start_data_blocks_loc) * BLOCKSIZE); - transmit_receive_bitmap(TRANSMIT, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, new_dir_block->block_num, 0); - }else{ - //get the current indirect block and check to see if it has room to add another data block: - if(!flag_free_cur_indirect_block){ - //if we don't have the indirect block, we need to get it from disk: - cur_indirect_block = (struct indirect_block*) kmalloc(BLOCKSIZE); - flag_free_cur_indirect_block = 1; - get_indirect_block(cur_inode, (cur_inode->indirect_blocks_in_file - 1), cur_indirect_block); - sd_receive((void*) dir_block, (cur_indirect_block->data_blocks[(cur_indirect_block->blocks_in_file)-1] + FS->start_data_blocks_loc)*BLOCKSIZE); - // kfree(cur_indirect_block); - } - if(cur_indirect_block->blocks_in_file < MAX_DATABLOCKS_PER_INDIRECT_BLOCK){ - //Case (2): add a new data block to to the current indirect block, then add the new_dir entry to the new data block: - cur_indirect_block->data_blocks[cur_indirect_block->blocks_in_file] = new_dir_block->block_num; - cur_indirect_block->blocks_in_file++; - - new_dir_block->dir_entries[new_dir_block->num_entries] = new_dir_entry; - new_dir_block->num_entries++; - cur_inode->size += sizeof(struct dir_entry); - - sd_transmit((void*) cur_indirect_block, (cur_indirect_block->block_num + FS->start_data_blocks_loc) * BLOCKSIZE); - sd_transmit((void*) new_dir_block, (new_dir_block->block_num + FS->start_data_blocks_loc) * BLOCKSIZE); - transmit_receive_bitmap(TRANSMIT, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, new_dir_block->block_num, 0); - }else{ - if(cur_inode->indirect_blocks_in_file < MAX_NUM_INDIRECT_BLOCKS){ - /* Case (3): add a new indirect block to the cur_inode, then add a new data block to the new indirect block, - then add the new dir_entry to the new data block: */ - int new_indirect_block_loc = bv_firstFree(data_block_bitmap); //Consult the data_block_bitmap to find a free block to add the new data block at - if (new_indirect_block_loc < 0) { //no free blocks - os_printf("disk space over \n"); - kfree(dir_block); - if (cur_indirect_block != NULL) { - kfree(cur_indirect_block); - } - return ERR_FULL; - } - struct indirect_block* new_indirect_block = (struct indirect_block*) kmalloc(BLOCKSIZE); - - new_indirect_block->blocks_in_file = 0; - new_indirect_block->block_num = new_indirect_block_loc; - - new_indirect_block->data_blocks[new_indirect_block->blocks_in_file] = new_dir_block->block_num; - new_indirect_block->blocks_in_file++; - cur_inode->indirect_blocks[cur_inode->indirect_blocks_in_file] = new_indirect_block->block_num; - cur_inode->indirect_blocks_in_file++; - - new_dir_block->dir_entries[new_dir_block->num_entries] = new_dir_entry; - new_dir_block->num_entries++; - cur_inode->size += sizeof(struct dir_entry); - - if(indirect_block_table_cache[new_indirect_block->block_num] == NULL){ - //TODO: implement eviction policy...add the cur_inode to the cache: - }else{ - *(indirect_block_table_cache[new_indirect_block->block_num]) = *(new_indirect_block); - } - bv_set(new_indirect_block_loc, data_block_bitmap); //taken - sd_transmit((void*) new_indirect_block, (new_indirect_block->block_num + FS->start_data_blocks_loc) * BLOCKSIZE); - sd_transmit((void*) new_dir_block, (new_dir_block->block_num + FS->start_data_blocks_loc) * BLOCKSIZE); - transmit_receive_bitmap(TRANSMIT, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, new_dir_block->block_num, 0); - kfree(new_indirect_block); - - }else{ - //file has reached max allowable size: - os_printf("ERROR! Operation failed because file has reached max allowable size\n"); - return ERR_FULL; - } - } - } - kfree(new_dir_block); - } - kfree(dir_block); - if(flag_free_cur_indirect_block){ - kfree(cur_indirect_block); - } - return SUCCESS; -}//end add_dir_entry() helper function - -/** - * Obtains address on disk of a specific data block within a file - * - * Uses the passed block number to search through the file's metadata and - * obtain a block address to read off the SD card - * - * @param - * - * inode *file_inode - points to the specific file in which the data block - * resides - * - * @param - * - * int file_block_num - holds the specific data block of the file to - * obtain the address from - * - * @return - * - * Returns 0 if address was successfully retrieved; otherwise returns -1 - */ -int get_block_address(struct inode *file_inode, int file_block_num){ - if(file_block_num < 0){ - os_printf("Invalid block number"); - return ERR_INVALID; - } - if(file_block_num < MAX_DATABLOCKS_PER_INODE){ - if (file_block_num >= file_inode->direct_blocks_in_file) { - return ERR_GEN; - } - return (file_inode->data_blocks[file_block_num] + FS->start_data_blocks_loc) * BLOCKSIZE; - } - //Block must be stored in an indirect block of file_inode - - //Get the indirect block num that contain the target block - int indirect_block_num = (file_block_num - MAX_DATABLOCKS_PER_INODE) / MAX_DATABLOCKS_PER_INDIRECT_BLOCK; - if(indirect_block_num >= file_inode->indirect_blocks_in_file || indirect_block_num > (MAX_NUM_INDIRECT_BLOCKS - 1)){ - return ERR_GEN; - } - - struct indirect_block* cur_indirect_block = (struct indirect_block*) kmalloc(sizeof(struct indirect_block)); - get_indirect_block(file_inode, file_inode->indirect_blocks[indirect_block_num], (struct indirect_block*) cur_indirect_block); - - int indirect_block_direct_block_num = (file_block_num - MAX_DATABLOCKS_PER_INODE) % MAX_DATABLOCKS_PER_INDIRECT_BLOCK; - if (cur_indirect_block->blocks_in_file <= indirect_block_direct_block_num) { - return ERR_GEN; - } - int block_address = cur_indirect_block->data_blocks[indirect_block_direct_block_num]; - block_address = (block_address + FS->start_data_blocks_loc) * BLOCKSIZE; - kfree(cur_indirect_block); - return block_address; -} - -/** - * Reads a partial portion of a block using the specified buffer size - * - * Reads a specified portion of a block from the passed file's inode - * starting at the offset point and then store the results of that in - * buf_offset - * - * @param - * - * struct inode *c_inode - The inode of the file we want to read - * - * @param - * - * int offset - starting point in the file to read from - * - * @param - * - * void* buf_offset - Holds the information read from the file - * - * @param - * - * int bytes_left - Holds the number of bytes to read from the file - * - * @param - * - * void* transfer_space - Used to hold data gotten from SD card block - * however I don't think we need this - * TODO: (maybe) replace transfer_space with buff_offset - * - * @return - * - * Returns the number of bytes which were transferred if successful; - * otherwise returns an error code - */ -int read_partial_block(struct inode *c_inode, int offset, void* buf_offset, int bytes_left, void* transfer_space) { - int local_offset = offset % BLOCKSIZE; // local_offset is the leftmost point in the block - - // Actually get the data for 1 block (the SD Driver will put it in transferSpace for us) - int file_block_num = offset / BLOCKSIZE; - int block_address = get_block_address(c_inode, file_block_num); - if (block_address < 0) { - return block_address; //return same error - } - - int success = sd_receive(transfer_space, block_address); - if(success < 0){ - // failed on a block receive, therefore the whole kread fails; return failure error - return ERR_SD; - }//end if block_num - - if((local_offset == 0) && (bytes_left < BLOCKSIZE)) { - /* ___________________ - |~~~~~~~~~| | - --------------------- */ - // Actually move the data to the user's specified buffer...must first cast void pointers to uint32_t* pointers: - // source is transfer_space - // dest is users buffer - - // note, this updates the buf_offset pointer as it transfer the data - // os_memcpy takes uint32_t* as arguments - os_memcpy(transfer_space, buf_offset, (os_size_t) bytes_left); - return bytes_left; // note, we are returning the number of bytes that were successfully transferred - - } else if((local_offset > 0) && (bytes_left >= (BLOCKSIZE - local_offset))) { - /* _____________________ - | |~~~~~~~~| - ---------------------- */ - // Actually move the data to the user's specified buffer...must first cast void pointers to uint32_t* pointers: - // source is transferSpace - // dest is users buffer - - os_memcpy((transfer_space + local_offset), buf_offset, (os_size_t) (BLOCKSIZE - local_offset)); // note, this updates the buf_offset pointer as it transfer the data - // os_memcpy takes uint32_t* as arguments - // reset transferSpace pointer - // transfer_space -= BLOCKSIZE; - - return (BLOCKSIZE - local_offset); // note, we are returning the number of bytes that were successfully transferred - - } else if((local_offset > 0) && (bytes_left < (BLOCKSIZE - local_offset))){ - /* ______________________ - | |~~~~| | - ----------------------- */ - // Actually move the data to the user's specified buffer...must first cast void pointers to uint32_t* pointers: - // source is transferSpace - // dest is users buffer - - os_memcpy((transfer_space + local_offset), buf_offset, (os_size_t) bytes_left); // note, this updates the buf_offset pointer as it transfer the data - // os_memcpy takes uint32_t* as arguments - // reset transferSpace pointer - transfer_space -= (local_offset + bytes_left); - - return bytes_left; // note, we are returning the number of bytes that were successfully transferred - - } - return ERR_GEN; -}//end of read_partial_block() helper function - - -/** - * Reads a full block using the specified buffer size - * - * Reads a specified block from the passed file's inode - * starting at the offset point and then store the results of that in - * buf_offset - * - * @param - * - * struct inode *c_inode - The inode of the file we want to read - * - * @param - * - * int offset - starting point in the file to read from - * - * @param - * - * void* buf_offset - Holds the information read from the file - * - * @param - * - * int bytes_left - Holds the number of bytes to read from the file - * - * @param - * - * void* transfer_space - Used to hold data gotten from SD card block - * however I don't think we need this - * TODO: (maybe) replace transfer_space with buff_offset - * - * @return - * - * Returns the number of bytes which were transferred if successful; - * otherwise returns an error code - */ -int read_full_block(struct inode *c_inode, int offset, void* buf_offset, int bytesLeft, void* transfer_space) { - // read BLOCKSIZE - // Actually get the data for 1 block (the SD Driver will put it in transfer_space for us) - int file_block_num = offset / BLOCKSIZE; - int block_address = get_block_address(c_inode, file_block_num); - if (block_address < 0) { - return block_address; //return same error - } - int success = sd_receive(transfer_space, block_address); - if(success < 0){ - // failed on a block receive, therefore the whole kread fails; return failure error - os_printf("failed to receive block number %d\n", file_block_num); - return ERR_SD; - }//end if - /* ______________________ - |~~~~~~~~~~~~~~~~~~~~~| - ----------------------- */ - // Actually move the data to the user's specified buffer...must first cast void pointers to uint32_t* pointers: - // source is transferSpace - // dest is users buffer - os_memcpy(transfer_space, buf_offset, (os_size_t) BLOCKSIZE); // note, this updates the buf_offset pointer as it transfer the data - // os_memcpy takes uint32_t* as arguments - // reset transferSpace pointer - return BLOCKSIZE; // note, we are returning the number of bytes that were successfully transferred -}//end read_full_block() helper function - -/** - * Reads the number of bytes specified from the target inode - * - * Calls either read_partial_block or read_full_block based on the number - * of bytes to read; will continue to call these functions until number of bytes - * specified has been met - * - * @param Description of method's or function's input parameter - * @param ... - * @return Description of the return value - */ -int read_inode(struct inode *c_inode, int offset, void* buf, int num_bytes){ - // Allocate space for and create a bitvector to be used repeatedly to transfer the data: - uint32_t *transfer_space = kmalloc(BLOCKSIZE); - int bytes_read = 0; - - if (num_bytes+offset > c_inode->size) { - num_bytes = c_inode->size - offset; - } - - // start of higher-level algo: - if(num_bytes < BLOCKSIZE) { - while(bytes_read < num_bytes) { - int x = read_partial_block(c_inode, offset + bytes_read, buf, (num_bytes-bytes_read),transfer_space); - bytes_read += x; - } - - } else if(num_bytes >= BLOCKSIZE) { - //Read in remainder of current block - bytes_read += read_partial_block(c_inode, offset + bytes_read, buf, (num_bytes-bytes_read),transfer_space); - //Read in maximum number of full blocks - while((num_bytes - bytes_read) >= BLOCKSIZE) { - bytes_read += read_full_block(c_inode, offset + bytes_read, buf+bytes_read, (num_bytes-bytes_read),transfer_space); - } - //If not completely read yet, read in remainder - if(bytes_read < num_bytes) { - bytes_read += read_partial_block(c_inode, offset + bytes_read, buf, (num_bytes-bytes_read),transfer_space); - } - }//end else if - - kfree(transfer_space); - return bytes_read; -} - - -//end of helper functions -// ----------------------------------------------------------------------------------------------------------------------------------------------------------- - -/** - * Kernel level open file; adds a new entry to the open file table - * - * Opens a file using the specified file path and sets it in either - * read or write mode. - * - * @param - * - * char* filepath - holds the pathname to the file to be opened - * - * @param - * - * char mode - holds either r or w indicating whether the file - * is to be opened in read or write mode - * - * @return - * - * Returns 0 if the file was opened correctly; otherwise returns - * -1 - * - */ -int kopen(const char* filepath, const char mode){ - if (filepath == NULL) { - os_printf("no directory specified \n"); - return ERR_INVALID; - } - if (mode == 0) { - os_printf("no mode specified \n"); - return ERR_INVALID; - } - int fd; - int inum = 0; - struct inode* cur_inode = (struct inode*) kmalloc(sizeof(struct inode)); - struct dir_helper* result = (struct dir_helper*) kmalloc(sizeof(struct dir_helper)); - kfind_dir(filepath, result); - int error = kfind_inode(filepath, inum, (result->dir_levels + 1), cur_inode); - - //here we have the file we were looking for! it is cur_inode. - if (error < 0 || cur_inode->is_dir) { - if (error < 0) { - os_printf("file not found, exiting kopen\n"); - } - else { - os_printf("cannot open a directory, make the path end to a file\n"); - error = ERR_INVALID; - } - kfree(cur_inode); - kfree(result->truncated_path); - kfree(result->last); - kfree(result); - - return error; //return same error - } - - // TODO: Permissions need some work, because the bitvector cannot be pulled out like this. :( - /*bit_vector *p = cur_inode->perms; - switch (mode){ - case 'r': - if(bv_get(0, p) == 0){ - os_printf("File Cannot Be Read\n"); - return -1; - } - break; - case 'w': - if(bv_get(1, p) == 0){ - os_printf("File Cannot Be Written\n"); - return -1; - } - break; - case 'a': - if(bv_get(1, p) == 0){ - os_printf("File Cannot Be Appeneded To\n"); - return -1; - } - break; - default: - os_printf("Please specify permission as r to read, w to write and a to append\n"); - }*/ - fd = add_to_opentable(cur_inode, mode); - kfree(result->truncated_path); - kfree(result->last); - kfree(result); - return fd; -}//end kopen() - -/** - * Reads a specified number of bytes from the SD card - * - * read from fd, put it in buf, then return the number of bytes read - * in numBytes - * - * @param - * - * int fd_int - index to a file descriptor in the open file table - * @param - * - * void* buf - buffer to hold the data read from the SD card - * - * @param - * - * int num_bytes - holds the number of bytes to store in the buffer - * - * @return - * - * Returns the number of bytes read from the SD card if successful, - * otherwise returns an error code - */ -int kread(int fd_int, void* buf, int num_bytes) { - if (fd_int < 0 || fd_int >= SYSTEM_SIZE) { - os_printf("kread, fd not valid \n"); - return ERR_INVALID; - } - if (buf == NULL) { - os_printf("no buffer \n"); - return ERR_INVALID; - } - if (num_bytes <= 0) { - os_printf("invalid number of bytes \n"); - return ERR_INVALID; - } - int bytes_read = 0; - uint32_t* buf_offset = buf; //this allows us to move data incrementally to user's buf via buf_offset - //while retaining the original pointer to return back to the user - struct file_descriptor* fd = get_descriptor(fd_int); // note, get_file_descriptor() function has not yet been implemented...will be in open_table.c - - if ((fd->permission != 'r') && (fd->permission != 'b')) { - os_printf("no permission\n"); - return ERR_PERM; - } - bytes_read = read_inode(fd->linked_file, fd->offset, buf_offset, num_bytes); - - fd->offset += bytes_read; - return bytes_read; -} // end kread(); - - -/** - * Write a specified number of bytes to the SD card - * - * write from fd, put it in buf, then return the number of bytes written in - * numBytes - * - * @param - * - * int fd_int - holds the index of a file descriptor in the open file table - * - * @param - * - * void* buf - holds the data to be written out to disk - * - * @param - * - * int num_bytes - holds the number of bytes to write to disk - * - * @return - * Returns the number of bytes written to disk if successful, otherwise - * returns an error code - */ -int kwrite(int fd_int, void* buf, int num_bytes) { - if (fd_int < 0 || fd_int >= SYSTEM_SIZE) { - os_printf("kwrite, fd not valid \n"); - return ERR_INVALID; - } - if (buf == NULL) { - os_printf("no buffer \n"); - return ERR_INVALID; - } - if (num_bytes <= 0) { - os_printf("invalid number of bytes \n"); - return ERR_INVALID; - } - struct file_descriptor* fd = get_descriptor(fd_int); - - if ((fd->permission != 'w' && fd->permission != 'a')){ - os_printf("ERROR! File was opened without write permissions.\nYou may or may not have permission to write to this file.\nTry opneing with 'w' permission\n"); - return ERR_PERM; - } - - int total_bytes_left = num_bytes; - int bytes_written = 0; - - struct indirect_block* cur_indirect_block; - void* buf_offset = buf; - void* transfer_space = kmalloc(BLOCKSIZE); - // os_memcpy(transferSpace, buf_offset, (os_size_t) BLOCKSIZE); - struct inode* cur_inode = fd->linked_file; - // have offset in the file already, just need to move it and copy. - // fd->offset is the offset in the file. - //while(bytes_written < total_bytes_left){ - while (total_bytes_left > 0) { - int file_block_num = fd->offset / BLOCKSIZE; - // need to put things in transfer_space, move pointer back when done - int offset_into_current_block = fd->offset % BLOCKSIZE; - int bytes_left_in_block = BLOCKSIZE - offset_into_current_block; - int block_address = get_block_address(cur_inode, file_block_num); - - //if get_block_address == -1, we know we need to allocate more space for the file - if(block_address < 0){ - int new_data_block_loc = bv_firstFree(data_block_bitmap); - if(new_data_block_loc < 0){//disk is completley full - os_printf("ERROR! disk full\n"); - return ERR_FULL; - } - block_address = (new_data_block_loc + FS->start_data_blocks_loc) * BLOCKSIZE; - bv_set(new_data_block_loc, data_block_bitmap); - - int flag_free_cur_indirect_block = 0; - if(cur_inode->direct_blocks_in_file < MAX_DATABLOCKS_PER_INODE){ - //Case (1): add a direct data block to cur_inode: - cur_inode->data_blocks[cur_inode->direct_blocks_in_file] = new_data_block_loc; - cur_inode->direct_blocks_in_file++; - transmit_receive_bitmap(TRANSMIT, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, new_data_block_loc, 0); - }else{//(cur_inode->direct_blocks_in_file >= MAX_DATABLOCKS_PER_INODE - //get the current indirect block and check to see if it has room to add another data block: - cur_indirect_block = (struct indirect_block*) kmalloc(BLOCKSIZE); - flag_free_cur_indirect_block = 1; - get_indirect_block(cur_inode, cur_inode->indirect_blocks[cur_inode->indirect_blocks_in_file-1], cur_indirect_block); - - if(cur_indirect_block->blocks_in_file < MAX_DATABLOCKS_PER_INDIRECT_BLOCK && cur_inode->indirect_blocks_in_file != 0){ - //Case (2): add a new data block to to the current indirect block: - cur_indirect_block->data_blocks[cur_indirect_block->blocks_in_file] = new_data_block_loc; - cur_indirect_block->blocks_in_file++; - - // Causes data abort errors for some reason. - /*if(indirect_block_table_cache[cur_indirect_block->block_num] == NULL){ - //TODO: implement eviction policy...add the cur_inode to the cache: - }else{ - *(indirect_block_table_cache[cur_indirect_block->block_num]) = *(cur_indirect_block); - }*/ - - sd_transmit((void*) cur_indirect_block, (cur_indirect_block->block_num + FS->start_data_blocks_loc) * BLOCKSIZE); - transmit_receive_bitmap(TRANSMIT, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, new_data_block_loc, 0); - }else{ //last indirect block full - if(cur_inode->indirect_blocks_in_file < MAX_NUM_INDIRECT_BLOCKS){ - /* Case (3): add a new indirect block to the cur_inode, then add a new data block to the new indirect block */ - int new_indirect_block_loc = bv_firstFree(data_block_bitmap); //Consult the data_block_bitmap to find a free block to add the new data block at - if(new_indirect_block_loc < 0){ - os_printf("ERROR! Disk full\n"); - return ERR_FULL; - } - bv_set(new_indirect_block_loc, data_block_bitmap); - - struct indirect_block* new_indirect_block = (struct indirect_block*) kmalloc(BLOCKSIZE); - new_indirect_block->blocks_in_file = 0; - new_indirect_block->block_num = new_indirect_block_loc; - - new_indirect_block->data_blocks[new_indirect_block->blocks_in_file] = new_data_block_loc; - new_indirect_block->blocks_in_file++; - cur_inode->indirect_blocks[cur_inode->indirect_blocks_in_file] = new_indirect_block_loc; - cur_inode->indirect_blocks_in_file++; - - /*if(indirect_block_table_cache[new_indirect_block->block_num] == NULL){ - //TODO: implement eviction policy...add the cur_inode to the cache: - }else{ - *(indirect_block_table_cache[new_indirect_block->block_num]) = *(new_indirect_block); - }*/ - - void *buf = kmalloc(BLOCKSIZE); - os_memcpy((uint32_t *) new_indirect_block, buf, sizeof(struct indirect_block)); - sd_transmit(buf, (new_indirect_block->block_num + FS->start_data_blocks_loc) * BLOCKSIZE); - kfree(buf); - transmit_receive_bitmap(TRANSMIT, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, new_indirect_block_loc, 0); - kfree(new_indirect_block); - - }else{ - //file has reached max allowable size: - os_printf("ERROR! Operation failed because file has reached max allowable size\n"); - return ERR_FULL; - } - } - } - if(flag_free_cur_indirect_block){ - kfree(cur_indirect_block); - } - }//end if(block_address == -1) - - //now we have added new blocks to the file if necessary (and possible), so actually execute the write: - if(total_bytes_left <= bytes_left_in_block){ - //note, that here we are overwriting, but will never have to allocate new data blocks for the file - /* --------------- ----------------- - |~~~~~~~| | OR | |~~~~~| | - ---------------- ----------------- - */ - //Remaining bytes to write will fit in the current block - //first read the block in, so that the first part of it doesn't get ovewritten: - sd_receive(transfer_space, block_address); - // write total_bytes_left - os_memcpy(buf_offset, transfer_space + offset_into_current_block, (os_size_t) total_bytes_left); - //transfer_space -= total_bytes_left; //Purpose of this? - // pointer to start, block_num, where we are in file, length of write - sd_transmit(transfer_space, block_address); - - bytes_written += total_bytes_left; - fd->offset += total_bytes_left; - cur_inode->size += total_bytes_left; - total_bytes_left = 0; //at this point there is nothing left to write, so we're done - } - else{//(total_bytes_left > bytes_left_in_block) so...we might need to allocate new data blocks for the file... - /* - ------------ - | |~~~| - ------------ - write to the end of the block - */ - - //Remaining bytes will not fit in current block, fill up remainder of block - //first read the block in, so that the first part of it doesn't get ovewritten: - sd_receive(transfer_space, block_address); - // write total_bytes_left - os_memcpy(buf_offset, transfer_space + offset_into_current_block, (os_size_t) bytes_left_in_block); - - //transfer_space -= bytes_left_in_block; //Purpose of this? - // pointer to start, blockNum, where we are in file, lengh of write - sd_transmit(transfer_space, block_address); - - bytes_written += bytes_left_in_block; - total_bytes_left -= bytes_left_in_block; - fd->offset += bytes_left_in_block; - buf_offset += bytes_left_in_block; - cur_inode->size += bytes_left_in_block; - } - - }//end while - //update the the cur_inode on disk: - sd_transmit(cur_inode, (cur_inode->inum + FS->start_inode_table_loc) * BLOCKSIZE); - return bytes_written; -} // end kwrite(); - -/** - * Close the file - * - * Remove the file from the open file table and free the file's inode - * - * @param - * - * int fd - holds an index of a file descriptor in the open file table - * - * @return - * - * Returns 1 if the file was successfully closed, otherwise returns an error - */ -int kclose(int fd) { - if (fd < 0 || fd >= SYSTEM_SIZE) { - os_printf("kclose, fd not valid \n"); - return ERR_INVALID; - } - int error; - if(!file_is_open(fd)) { - os_printf("file not open"); - return ERR_GEN; - } - error = delete_from_opentable(fd); //this also frees inode - return error; -} // end kclose(); - -/** - * Increment seek position within a file - * - * Increments the seek pointer of a specific file by a number of - * specified bytes - * - * @param - * - * int fd_int - holds the index of a file descriptor in the open file table - * - * @param - * - * int num_bytes - holds the number of bytes to move the seek pointer by - * - * @return - * - * Returns 0 if the seek pointer was successfully moved; otherwise returns - * an error code - */ -int kseek(int fd_int, int num_bytes) { - if (fd_int < 0 || fd_int >= SYSTEM_SIZE) { - os_printf("kseek, fd not valid \n"); - return ERR_INVALID; - } - if (num_bytes <= 0) { - os_printf("num of bytes not valid \n"); - return ERR_INVALID; - } - struct file_descriptor* fd = get_descriptor(fd_int); - if (fd->permission != 'r' || fd->permission != 'w') { - os_printf("no permission \n"); - return ERR_PERM; - } else if ((num_bytes > 0) && ((fd->offset + num_bytes) > ((fd->linked_file)->size))){ - os_printf("Error! file offset exceeds file size \n"); - return ERR_GEN; - } else if ((num_bytes < 0) && ((fd->offset + num_bytes) < 0)){ - os_printf("Error! file offset exceeds beginning of file \n"); - return ERR_GEN; - }//end if else */ - fd->offset += num_bytes; - return SUCCESS; -} // end kseek(); - - -/** - * Creates a new file or directory in the file system - * - * Creates a new file or directory and all metadata attached to that - * file or directory and adds it to the open file table - * - * NOTE: File/Directory is not persistenly stored at this point! - * - * @param - * - * char* filepath - holds the path to the directory in which the - * new file/directory is to be added - * - * @param - * - * char mode - not used at present, will eventually be used to - * set file permissions - * - * @param - * - * int is_this_a_dir - set to 0 if the object to be created is - * a file; set to 1 if the object to be created is a directory - * - * @return - * - * Returns 0 if the file/directory was created successfully - * otherwise returns -1 - */ -int kcreate(const char* filepath, char mode, int is_this_a_dir) { - if (filepath == NULL) { - os_printf("filepath not valid \n"); - return ERR_INVALID; - } - if (mode == 0) { - os_printf("filepath not valid \n"); - return ERR_INVALID; - } - int fd; - int inum = 0; - struct inode* cur_inode = (struct inode*) kmalloc(sizeof(struct inode)); - struct dir_helper* result = (struct dir_helper*) kmalloc(sizeof(struct dir_helper)); - kfind_dir(filepath, result); - kfind_inode(result->truncated_path, inum, result->dir_levels, cur_inode); - - // at this point, the name of the file or dir to be created is “result->last” and it has to be added to cur_inode - int free_inode_loc = bv_firstFree(inode_bitmap); //Consult the inode_bitmap to find a free space in the inode_table to add the new inode - - if (free_inode_loc < 0) { - os_printf("Disk has reached max number of files allowed. \n"); - kfree(cur_inode); - kfree(result->truncated_path); - kfree(result->last); - kfree(result); - return ERR_FULL; - } - bv_set(free_inode_loc, inode_bitmap); - struct inode * new_inode = (struct inode*) kmalloc(sizeof(struct inode)); // Create the new inode - - /* initialize all fields of inode...note, these next 5 fields are for - all files, whether they are a dir or leaf */ - new_inode->inum = free_inode_loc; - new_inode->fd_refs = 0; //will be incremented in add to opentable - new_inode->size = 0; - new_inode->usr_id = 0; //or something - new_inode->indirect_blocks_in_file = 0; - - /* initialize the fields for new_indoe that are different for dirs and leaves */ - if(is_this_a_dir){ - new_inode->is_dir = 1; - new_inode->direct_blocks_in_file = 1; - - // Lay down the first (empty...) data block for the new directory (NOT root). - - transmit_receive_bitmap(RECEIVE, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, 0, 1); - int new_data_block_loc = bv_firstFree(data_block_bitmap); - if(new_data_block_loc < 0){//disk is completley full - os_printf("ERROR! disk full\n"); - return ERR_FULL; - }//end if - int block_address = (new_data_block_loc + FS->start_data_blocks_loc) * BLOCKSIZE; - bv_set(new_data_block_loc, data_block_bitmap); - - //WILL THIS FIX IT?????????? - transmit_receive_bitmap(TRANSMIT, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, 0, 1); - - void *block = kmalloc(BLOCKSIZE); - os_memset(block, 0, BLOCKSIZE); - struct dir_data_block ddb; - ddb.block_num = new_data_block_loc; - ddb.num_entries = 0; - os_memset(block, 0, BLOCKSIZE); - os_memcpy((uint32_t*)&ddb, block, sizeof(struct dir_data_block)); - sd_transmit((void*)block, block_address); - new_inode->data_blocks[0] = new_data_block_loc; - kfree(block); - }else{ /* initialize the fields for new_inode that are different for dirs and leaves */ - new_inode->is_dir = 0; - new_inode->direct_blocks_in_file = 0; - }//end if else - - //new_inode->data_blocks[MAX_DATABLOCKS_PER_INODE] = {0}; - - //new_inode->indirect_blocks[MAX_NUM_INDIRECT_BLOCKS] = {0}; - // TODO: Investigate permissions, and bitvectors/FS in general. - /*switch (mode){ - case 'r': - bv_set(0, new_inode->perms); - bv_lower(1, new_inode->perms); - break; - case 'w': - bv_set(0, new_inode->perms); - bv_set(1, new_inode->perms); - break; - default: - os_printf("Wrong permission. Please insert r for read and w for write\n"); - return -1; - }*/ - //UPDATE DISK by writing memory data structures to disk - - int error = add_dir_entry(cur_inode, new_inode->inum, result); - if (error != 0) { - return error; - } - void *block = kmalloc(BLOCKSIZE); - os_memset(block, 0, BLOCKSIZE); - os_memcpy((uint32_t*)cur_inode, block, sizeof(struct inode)); - sd_transmit(block, (cur_inode->inum + FS->start_inode_table_loc) * BLOCKSIZE); - - os_memset(block, 0, BLOCKSIZE); - os_memcpy((uint32_t*)new_inode, block, sizeof(struct inode)); - sd_transmit(block, (FS->start_inode_table_loc + new_inode->inum * INODES_PER_BLOCK)*BLOCKSIZE); //if there are more than 1 inodeperblock need to change - kfree(block); - // See above... We can't just do this. - //sd_transmit((void*)inode_bitmap, FS->inode_bitmap_loc); - kfree(cur_inode); - if (!is_this_a_dir) { - fd = add_to_opentable(new_inode, mode); - return fd; - }else { //directories are not added to open table - os_printf("Directory Successfully added\n"); - kfree(new_inode); - return SUCCESS; - } - -}//end of kcreate() function - -/** - * Determines whether a directory is empty or not - * - * Determines whether a directory is empty, can also be used to - * determine whether the object is a file instead of a directory as - * well as if the file is not a valid Course OS FS file - * - * @param - * - * struct inode* cur_inode - holds the file/directory to check - * - * @return - * - * Return 1 if it is a directory, return 0 if it not a directory, - * return an error code if something went wrong - */ -int dir_empty(struct inode* cur_inode){ - if(!cur_inode->is_dir){ - os_printf("This file is not a directory\n"); - return FALSE;//return 0, because it's not a dir - }//end else - if((cur_inode->direct_blocks_in_file == 0) && (cur_inode->indirect_blocks_in_file == 0)){ - if(cur_inode->size == 0){ - return TRUE; //return true because the dir is empty - } else { - /* TODO: Remove after debugging */ - os_printf("LOGIC ERROR: File size does not sync with file properties"); - return ERR_GEN;//error bc we should never get here - } - } - else { - os_printf("Your current directory still has files in it\n"); - return FALSE;//return false, bc the dir is not empty - } -} - -/** - * Helper function for kremove_dir_entry actually deletes file/directory - * - * Runs after entry for the file/directory has been removed from the parent - * directory and physically deletes the file/directory - * - * @param - * - * struct inode* cur_inode - inode of the file to check - * - * @return - * - * Returns 0 if the file is OK to remove, otherwise returns an error code - */ -int kdelete_single_helper(struct inode * cur_inode){ - if (cur_inode->is_dir){ - //we know it's a directory - if(dir_empty(cur_inode)) { - - bv_lower(cur_inode->inum, inode_bitmap); - return SUCCESS;//no error - } - else { - os_printf("This file is a non-empty directory, so cannot be deleted"); - return ERR_GEN;//error - } - } - //we know it is a file - else{ - int d; - for(d=0; ddirect_blocks_in_file; d++){ - - int index = cur_inode->data_blocks[d]; - bv_lower(index, data_block_bitmap); - } - struct indirect_block* cur_inder_block = (struct indirect_block*)kmalloc(sizeof(struct indirect_block)); - int i; - for(i=0; iindirect_blocks_in_file; i++){ - int z; - int indy_index_add = (cur_inode->indirect_blocks[i] + FS->start_data_blocks_loc) * BLOCKSIZE; - sd_receive((void*)cur_inder_block, indy_index_add); - for(z=0; zblocks_in_file; z++){ - - int index = cur_inder_block->data_blocks[z]; - bv_lower(index, data_block_bitmap); - } - bv_lower(cur_inder_block->block_num, data_block_bitmap); - } - kfree(cur_inder_block); - bv_lower(cur_inode->inum, inode_bitmap); - } - return SUCCESS; -} // end kdelete_single_helper(); - -/** - * Deletes a single entry in a directory - * - * Deletes a file or directory's entry from a specified directory's inode list - * NOTE: May/May not use recursive delete; this is untested so proceed - * with caution and test whether a recursive delete is done before - * using this function for deleting sub-directories. - * - * @param - * - * struct inode* cur_inode - holds a pointer to the folder which contains the file - * reference to remove - * - * @param - * - * int tgt_inum - Used to hold the index of the inode to be removed - * - * @return - * - * Returns 0 if the entry was successfully removed from the directory; otherwise - * it returns an error code. - */ -int kremove_dir_entry (struct inode* cur_inode, int tgt_inum) {//free_inode_loc = tgt_inum - //first get the appropriate data block, either from the array of direct data blocks from an indirect block: - struct dir_data_block* dir_block = (struct dir_data_block*) kmalloc(BLOCKSIZE); - struct indirect_block* cur_indirect_block; - //if the cur_inode's array of direct data blocks has not reached max capacity, grab the last data block in the array to update: - int i, j, k; - //search through direct data blocks: - for(i = 0; i < cur_inode->direct_blocks_in_file; i++){ - sd_receive((void*) dir_block, (cur_inode->data_blocks[i] + FS->start_data_blocks_loc)*BLOCKSIZE); - for(j = 0; j < dir_block->num_entries; j++){ - struct dir_entry dir_ent = (struct dir_entry) dir_block->dir_entries[j]; - if(dir_ent.inum == tgt_inum){ - /* remove dir_ent from dir_block, by moving the last dir_entry to this - index in the array and decrementing dir_block->num_entries */ - dir_block->dir_entries[j] = dir_block->dir_entries[dir_block->num_entries-1]; - dir_block->num_entries--; - if(dir_block->num_entries == 0){ - /* then this dir_data_block is empty, so we need to: - remove it from the cur_inode->data_blocks[] at index i - remove it from the data_blocks_bitmap */ - bv_lower(cur_inode->data_blocks[i], data_block_bitmap); - cur_inode->data_blocks[i] = cur_inode->data_blocks[cur_inode->direct_blocks_in_file-1]; - cur_inode->direct_blocks_in_file--; - }//end if - cur_inode->size -= sizeof(struct dir_entry); - sd_transmit((void*) dir_block, (cur_inode->data_blocks[i] + FS->start_data_blocks_loc)*BLOCKSIZE); - kfree(dir_block); - return SUCCESS; - }//end if - }//end for - }//end outer for - //search through indirect data blocks: - cur_indirect_block = (struct indirect_block*) kmalloc(BLOCKSIZE); - for(k = 0; k < cur_inode->indirect_blocks_in_file; k++){ - get_indirect_block(cur_inode, k, cur_indirect_block); - for(i = 0; i < cur_indirect_block->blocks_in_file; i++){ - sd_receive((void*) dir_block, (cur_indirect_block->data_blocks[i] + FS->start_data_blocks_loc)*BLOCKSIZE); - for(j = 0; j < dir_block->num_entries; j++){ - struct dir_entry dir_ent = (struct dir_entry) dir_block->dir_entries[j]; - if(dir_ent.inum == tgt_inum){ - /* remove dir_ent from dir_block, by moving the last dir_entry to this - index in the array and decrementing dir_block->num_entries */ - dir_block->dir_entries[j] = dir_block->dir_entries[dir_block->num_entries-1]; - dir_block->num_entries--; - if(dir_block->num_entries == 0){ - /* then this dir_data_block is empty, so we need to: - remove it from the cur_inode->data_blocks[] at index i - remove it from the data_blocks_bitmap */ - bv_lower(cur_indirect_block->data_blocks[i], data_block_bitmap); - cur_indirect_block->data_blocks[i] = cur_indirect_block->data_blocks[cur_inode->direct_blocks_in_file-1]; - cur_indirect_block->blocks_in_file--; - - if(cur_indirect_block->blocks_in_file == 0){ - /* then this indirect_block is empty, so we need to: - remove it from the cur_inode->indirect_blocks[] at index k - remove it from the data_blocks_bitmap */ - bv_lower(cur_inode->indirect_blocks[k],data_block_bitmap); - cur_inode->indirect_blocks[k] = cur_inode->indirect_blocks[cur_inode->indirect_blocks_in_file-1]; - cur_inode->indirect_blocks_in_file--; - }//end if - }//end if - cur_inode->size -= sizeof(struct dir_entry); - sd_transmit((void*) dir_block, (cur_indirect_block->data_blocks[i] + FS->start_data_blocks_loc)*BLOCKSIZE); - kfree(dir_block); - kfree(cur_indirect_block); - return SUCCESS; - }//end if - }//end for - }//end outer for - }//end outer outer for - kfree(dir_block); - kfree(cur_indirect_block); - return ERR_404; -}//end kremove_dir_entry() function - - -/** - * Deletes a single file or from a directory - * - * call delete_single_helper, deletes the lowest level (ie target) file and - * updates all bitmaps, but DOES NOT remove the dir_entry in levelup dir - * - * @param - * - * struct inode* cur_inode - Points to a specific file/directory to remove - * - * @param - * - * struct inode* level_up_inode - points to the directory in which the specifiied - * file/directory resides - * - * @return - * - * Returns 0 if the the file was successfully deleted; returns -1 if the file - * doesn't exist - */ -int kdelete_single(struct inode* cur_inode, struct inode* level_up_inode) { - /* call delete_single_helper, deletes the lowest level (ie target) file and - updates all bitmaps, but DOES NOT remove the dir_entry in levelup dir */ - int error = kdelete_single_helper(cur_inode); - if(!error){ //if kdeletesinglehelper was successful - sd_transmit((void*) cur_inode, (cur_inode->inum + FS->start_inode_table_loc) * BLOCKSIZE); - /* delete dir_entry in levelup dir) */ - error = kremove_dir_entry(level_up_inode, cur_inode->inum); - if(error < 0){ - os_printf("ERROR! Could not find dir_entry in level_up_inode...BIG PROBLEM!!!\n"); - kfree(level_up_inode); - return error; - }//end inner if - sd_transmit((void*) cur_inode, (level_up_inode->inum + FS->start_inode_table_loc) * BLOCKSIZE); - }else{ - kfree(level_up_inode); - return error; //return same error - } - kfree(level_up_inode); - return SUCCESS; -} // end kdelete_single() - - -/** - * Recursively deletes an entire directory - * - * Deletes a directory and any sub-directories and files contained within - * freeing all blocks and metadata for each entry and then updates the - * metadata for the directory which contained it - * - * The logic on this should be good, but still need to... - * TODO: on each sd_recieve() check cache first AND figure out kmalloc - * situation...will this cause heap overflow??? should we limit the - * depth of filepaths to avoid this??? - * - * @param - * - * struct inode* cur_inode - Points to a specific file/directory to remove - * - * @param - * - * struct inode* level_up_inode - points to the directory in which the specifiied - * file/directory resides - * - * @return - * - * Returns 0 if the the directory was successfully deleted, otherwise returns - * an error code - */ -int krec_delete(struct inode * level_up_inode, struct inode * cur_inode){ - //base case - int error; - int status = dir_empty(cur_inode); - if (status == TRUE){ //dir is empty - error = kdelete_single(cur_inode, level_up_inode); - //SHOULDN'T FREE IT kfree(level_up_inode); - }else if(status < 0){ //WTF? - return ERR_GEN; - } - - if (error) { - return error; - } - - //recursive step - else{ //status == 0, meaning is not empty - int i; - int direct_data_block_address; - struct dir_data_block* dir_block = (struct dir_data_block*) kmalloc(sizeof(struct dir_data_block)); - for(i=0; i< cur_inode->direct_blocks_in_file; i++){ - direct_data_block_address = (cur_inode->data_blocks[i]+FS->start_data_blocks_loc) * BLOCKSIZE; - sd_receive(dir_block, direct_data_block_address); - int j; - int inum; - struct dir_entry cur_dir_entry; - for(j = 0; j < dir_block->num_entries; j++){ - cur_dir_entry = dir_block->dir_entries[j]; - inum = cur_dir_entry.inum; - struct inode* next_inode = (struct inode*) kmalloc(sizeof(struct inode)); - // struct inode* next_inode; - get_inode(inum, next_inode); - krec_delete(cur_inode,next_inode); - kfree(next_inode); - }//end - }//end for - int k; - int indirect_data_block_address; - struct indirect_block* cur_indirect_block = (struct indirect_block*) kmalloc(sizeof(struct indirect_block)); - for(k = 0; k < cur_inode->indirect_blocks_in_file; k++){ - indirect_data_block_address = (cur_inode->indirect_blocks[k]+FS->start_data_blocks_loc) * BLOCKSIZE; - sd_receive(cur_indirect_block, indirect_data_block_address); - for(i=0; i < cur_indirect_block->blocks_in_file; i++){ - direct_data_block_address = (cur_indirect_block->data_blocks[i]+FS->start_data_blocks_loc) * BLOCKSIZE; - sd_receive(dir_block, direct_data_block_address); - int j; - int inum; - struct dir_entry cur_dir_entry; - for(j = 0; j < dir_block->num_entries; j++){ - cur_dir_entry = dir_block->dir_entries[j]; - inum = cur_dir_entry.inum; - struct inode* next_inode = (struct inode*) kmalloc(sizeof(struct inode)); - // struct inode* next_inode; - get_inode(inum, next_inode); - krec_delete(cur_inode,next_inode); - kfree(next_inode); - }//end - }//end - }//end outer for - kfree(cur_indirect_block); - kfree(dir_block); - }//end if else - return SUCCESS; -}//end krec_delete() - -//--------------------------------------------------- - -/** - * Deletes a file or directory at the specified filepath - * - * Can be used to delete a single file or directory; can delete - * directories recursively - * - * NOTE: Recursive delete is untested; please test this function - * to ensure it is working properly before using it - * - * @param - * - * char* filepath - Holds the path to the specified file/directory to delete - * - * @param - * - * int recursive - Holds 0 if the target is a single file or empty directory - * holds 1 if the target is a full directory which needs to be deleted recursively - * - * @return - * - * Returns 0 if the file/directory was deleted successfully; otherwise returns an - * error code - */ -//delete the file or directory at filepath. Return -1 if the file does not exist -int kdelete(const char* filepath, int recursive) { - int error; - int inum = 0; - - /* spaceholder for lowest inode */ - struct inode* cur_inode = (struct inode*) kmalloc(sizeof(struct inode)); - struct inode* level_up_inode = (struct inode*) kmalloc(sizeof(struct inode)); - /* spaceholder for helper struct */ - struct dir_helper* result = (struct dir_helper*) kmalloc(sizeof(struct dir_helper)); - - /* find the helper struct */ - kfind_dir(filepath, result); - - /* find the lowest inode */ - error = kfind_inode(filepath, inum, (result->dir_levels + 1), cur_inode); - if(error < 0){ - kfree(cur_inode); - kfree(level_up_inode); - kfree(result->truncated_path); - kfree(result->last); - kfree(result); - return error; - } - /* Check to ensure the file is not currently open...if it is return an error and notify user */ - if(inode_is_open(cur_inode)){ - os_printf("File %d cannot be deleted, because it is currently open\n", cur_inode->inum); - kfree(cur_inode); - kfree(level_up_inode); - kfree(result->truncated_path); - kfree(result->last); - kfree(result); - return ERR_GEN; - } - error = kfind_inode(filepath, inum, (result->dir_levels), level_up_inode); - if(recursive){ - error = krec_delete(level_up_inode,cur_inode); - kfree(cur_inode); - kfree(level_up_inode); - kfree(result->truncated_path); - kfree(result->last); - kfree(result); - transmit_receive_bitmap(TRANSMIT, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, 0, 1); - transmit_receive_bitmap(TRANSMIT, inode_bitmap, FS->inode_bitmap_loc, FS->max_inodes, 0, 1); - return error; - }else{ - error = kdelete_single(cur_inode, level_up_inode); - kfree(cur_inode); - kfree(level_up_inode); - kfree(result->truncated_path); - kfree(result->last); - kfree(result); - transmit_receive_bitmap(TRANSMIT, data_block_bitmap, FS->data_bitmap_loc, FS->max_data_blocks, 0, 1); - transmit_receive_bitmap(TRANSMIT, inode_bitmap, FS->inode_bitmap_loc, FS->max_inodes, 0, 1); - return error; - }//end if else - os_printf("we should never reach this!!!\n"); - return ERR_GEN; -} // end kdelete() - - -//--------------------------------------------------- - -/** - * Copies contents of a file into a new file - * - * Creates a new file at the destination path and then copies - * all data from the file pointed to by the source path - * - * @param - * - * char* source - holds the file path of the file to copy - * - * @param - * - * char* dest - holds the destination file path to copy to - * - * @param - * - * char mode - Mainly used for permissions; not implemented right - * now however - * - * @return - * - * Retun 0 if the file was copied successfully; otherwise return - * an error code - */ -int kcopy(const char* source, const char* dest, const char mode) { - int error = 0; - int inum = 0; //start from root - - //1. find source - struct dir_helper *source_dir_helper = (struct dir_helper *) kmalloc(sizeof(struct dir_helper)); - kfind_dir(source, source_dir_helper); - struct inode *source_inode = (struct inode*) kmalloc(sizeof(struct inode)); - //find the source inode - error = kfind_inode(source, inum, (source_dir_helper->dir_levels + 1), source_inode); - if (error < 0) { //kfind_inode unsuccessful - os_printf("kfind_inode unsuccessful \n"); - kfree(source_inode); - kfree(source_dir_helper->truncated_path); - kfree(source_dir_helper->last); - kfree(source_dir_helper); - return ERR_404; - } - //at this point source_inode is the inode of the source - int copy_directory = source_inode->is_dir; //checks if we are copying a direcory or a file - - //2. cerate destination - int dest_fd = 0; - dest_fd = kcreate(dest, mode, copy_directory); //creates the new file or directory - if (dest_fd < 0) { //some problem occurred in kcreate - os_printf("kcreate unsuccessful \n"); - kfree(source_inode); - kfree(source_dir_helper->truncated_path); - kfree(source_dir_helper->last); - kfree(source_dir_helper); - return ERR_GEN; - } - - //3. find destination - struct file_descriptor *dest_fd_struct = get_descriptor(dest_fd); - if (dest_fd_struct == NULL) { //get_descriptor had problems - os_printf("get_descriptor unsuccessful \n"); - kfree(source_inode); - kfree(source_dir_helper->truncated_path); - kfree(source_dir_helper->last); - kfree(source_dir_helper); - return ERR_GEN; - } - //at this point dest_inode is the inode of the created destination - - void *buffer = (void*) kmalloc(source_inode->size); - error = read_inode(source_inode, 0, buffer, source_inode->size); - if (!error) { - error = kwrite(dest_fd, buffer, source_inode->size); - } - kfree(buffer); - kfree(source_inode); - kfree(source_dir_helper->truncated_path); - kfree(source_dir_helper->last); - kfree(source_dir_helper); - return error; -}//end kcopy function - - -/** - * Prints the contents of a directory to the screen - * - * @param - * - * char* filepath - holds the filepath to the directory to display - * the contents of - * - * @return - * Returns 0 if the function was executed correctly, otherwise returns - * an error code - */ -int kls(const char* filepath) { - int error = 0; - int inum = 0; //starting from root - struct dir_helper* result = (struct dir_helper *) kmalloc(sizeof(struct dir_helper)); - kfind_dir(filepath, result); - struct inode* cur_inode = (struct inode*) kmalloc(sizeof(struct inode)); - error = kfind_inode(filepath, inum, (result->dir_levels + 1), cur_inode); - if (error < 0 || cur_inode->is_dir == 0) { //kfind_inode unsuccessful or cannot ls - if (error < 0) { //kfind - os_printf("kfind_inode unsuccessful \n"); - } - else { //cannot ls - os_printf("this is not a directory but a file, cannot ls a file \n"); - error = ERR_INVALID; - } - kfree(cur_inode); - kfree(result->truncated_path); - kfree(result->last); - kfree(result); - return error; //return same error - } - //at this point, cur_inode is a directory and we need to print all the names of its contents. - //1. print from direct blocks - int i; - void* dir_spaceholder = (void*) kmalloc(BLOCKSIZE); - for(i = 0; i < cur_inode->direct_blocks_in_file; i++){ - sd_receive(dir_spaceholder, (cur_inode->data_blocks[i])*BLOCKSIZE); - struct dir_data_block cur_data_block = *((struct dir_data_block*) dir_spaceholder); - int j; - for(j = 0; j < (cur_data_block.num_entries); j++){ - struct dir_entry file_dir = cur_data_block.dir_entries[j]; - os_printf("entry: %s \n", file_dir.name); - }//inner for - }//outer for - //2. print from indirect blocks - struct indirect_block *cur_indirect_block = (struct indirect_block *) kmalloc(sizeof(struct indirect_block)); - int cur_indirect_block_num; - for(i = 0; i < cur_inode->indirect_blocks_in_file; i++){ - cur_indirect_block_num = cur_inode->indirect_blocks[i]; - get_indirect_block(cur_inode, cur_indirect_block_num, cur_indirect_block); - int j; - for(j = 0; j < cur_indirect_block->blocks_in_file; j++){ - sd_receive(dir_spaceholder, (cur_indirect_block->data_blocks[j])*BLOCKSIZE); - struct dir_data_block cur_data_block = *((struct dir_data_block*) dir_spaceholder); - int k; - for(k = 0; k < (cur_data_block.num_entries); k++){ - struct dir_entry file_dir = cur_data_block.dir_entries[k]; - os_printf("entry: %s \n", file_dir.name); - }//inner for - }//outer for - }//end for - kfree(cur_indirect_block); - kfree(dir_spaceholder); - kfree(cur_inode); - kfree(result->truncated_path); - kfree(result->last); - kfree(result); - return SUCCESS; -} - -/** - * Used to obtain information about a specified file or directory - * - * Obtains various information about the file at the specified file - * path including: size of the file, how many open copies of the - * file there are, and whether the file is a directory - * - * @param - * - * char* filepath - The path to the file to obtain information from - * - * @param - * - * struct stats* result - Pointer to a location to store information - * about the specified file - * - * @return - * Returns 0 if information was successfully retrieved; otherwise - * returns an error code - */ -int get_stats(const char * filepath, struct stats * result) { - int inum = 0; - struct inode* cur_inode = (struct inode*) kmalloc(sizeof(struct inode)); - struct dir_helper* help_result = (struct dir_helper*) kmalloc(sizeof(struct dir_helper)); - kfind_dir(filepath, help_result); - int error = kfind_inode(filepath, inum, (help_result->dir_levels + 1), cur_inode); - if (error < 0) { - os_printf("file not found, exiting kopen\n"); - kfree(cur_inode); - kfree(help_result->truncated_path); - kfree(help_result->last); - kfree(help_result); - return error; //return same error - } - result->size = cur_inode->size; - result->fd_refs = cur_inode->fd_refs; - result->is_dir = cur_inode->is_dir; - kfree(cur_inode); - kfree(help_result->truncated_path); - kfree(help_result->last); - kfree(help_result); - return SUCCESS; -}//end get_stats function diff --git a/kernel/fs/fat16/test.c b/kernel/fs/fat16/test.c deleted file mode 100644 index 5f002434..00000000 --- a/kernel/fs/fat16/test.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include - - -int main(int argc, char *argv[]) { - char cwd[1024]; - if (getcwd(cwd, sizeof(cwd)) != NULL) - fprintf(stdout, "Current working dir: %s\n", cwd); - else - perror("getcwd() error"); - - char* buf = (void*) malloc(sizeof(char) * 512); - char* original_buf = buf; - *buf = "courseOSfsaaaaaaaaaaaaaaaaaaaaa"; - buf +=32; - - *((int*)buf) = (int)1; - buf +=4; - - buf = (int*)buf; - - *(buf) = (int)2; - buf +=4; - - *(buf) = (int)512; - buf +=4; - - *(buf) = (int)2; - buf +=4; - - *(buf) = (int)100; - buf +=4; - - *(buf) = (int)900; - buf +=4; - - *(buf) = (int)11; - buf +=4; - - *(buf) = (int)12; - buf +=4; - - *(buf) = (int)333; - buf +=4; - - *(buf) = (int)444; - buf +=4; - - // 12 512000 512 2 100 900 11 12 333 444 - fprintf("TESTING***************\n") - int fd = open("superblock_1.data", 'O_RDWR'); - write(fd, original_buf, 512); - close(fd); - - - // FILE *params_file = fopen("superblock_1.data", "w"); // write only - // // test to ensure that the file was actually created and exists: - // if (params_file == NULL){ - // printf("1. Error! Could not create file\n"); - // exit(-1); // must include stdlib.h - // }//end if - - // fprintf(params_file, "PARAMS\n"); - // fprintf(params_file, "nx=%d,ny=%d,nz=%d\n", nx, ny, nz); - // fprintf(params_file, "dx=%lg,dy=%lg,dz=%lg\n", dx, dy, dz); - // fprintf(params_file, "numFiles=%d\n", numFiles); - // fprintf(params_file, "numParticles=%d\n", numParticles); - // fclose(params_file); - - - - return 0; -} diff --git a/kernel/fs/fat16/test_superblock.data b/kernel/fs/fat16/test_superblock.data deleted file mode 100644 index cca4d90a..00000000 --- a/kernel/fs/fat16/test_superblock.data +++ /dev/null @@ -1 +0,0 @@ -courseOSfsaaaaaaaaaaaaaaaaaaaaaa1 2 512000 512 2 100 900 11 12 333 444 \ No newline at end of file diff --git a/kernel/fs/fat16/test_superblock.txt b/kernel/fs/fat16/test_superblock.txt deleted file mode 100644 index cca4d90a..00000000 --- a/kernel/fs/fat16/test_superblock.txt +++ /dev/null @@ -1 +0,0 @@ -courseOSfsaaaaaaaaaaaaaaaaaaaaaa1 2 512000 512 2 100 900 11 12 333 444 \ No newline at end of file diff --git a/kernel/fs/open_table.c b/kernel/fs/open_table.c deleted file mode 100644 index efa075ac..00000000 --- a/kernel/fs/open_table.c +++ /dev/null @@ -1,117 +0,0 @@ -//This file contains the table of open files, implemented as an array -// with methods like add_to_opentable and delete_from_opentable to be called in open and close -//Since methods are provided, other files should not touch neither the free LL or the arrray, -// but just use the premade methods. - -#include "klibc.h" -#include "fs/file.h" -#include "fs/open_table.h" -#include "data_structures/bitvector.h" -#include - - -//called by file.c initialization function, initializes free list and table -void fs_table_init() { - open_table_free_list = make_vector(SYSTEM_SIZE); //create bitvector of free indexes - table = (struct file_descriptor**)kmalloc(SYSTEM_SIZE * (sizeof(struct file_descriptor*))); //malloc the table - os_memset(table, 0, SYSTEM_SIZE * (sizeof(struct file_descriptor*))); -} - -//at shutdown, memory with the free list is freed -void fs_table_shutdown() { - bv_free(open_table_free_list); - int i; - for (i = 0; i < SYSTEM_SIZE; i++) { - if (table[i] != NULL) { //deal with users that forget to close files - if (table[i]->linked_file != NULL) { //"if" added because we never know what can happen... - kfree(table[i]->linked_file); - } - kfree(table[i]); - } - } - kfree(table); -} - - -//returns struct of descriptor at index fd -//if invalid, returns NULL. -struct file_descriptor* get_descriptor(int fd){ - if (file_is_open(fd)) { - return table[fd]; - } - return NULL; -} - -// this function can be used to insert a file in the table -// and returns the requested index if successful, else -1 -int add_to_opentable(struct inode * f, char perm) { - int fd = (int) bv_firstFree(open_table_free_list); //gets free index from bitvector - if (fd == -1) { - return ERR_FULL; //reached max num of files open - } - bv_set((uint32_t)fd, open_table_free_list); //index is now taken - struct file_descriptor* to_add = (struct file_descriptor*) kmalloc(sizeof(struct file_descriptor)); //malloc new struct - int inum = f->inum; - int i; - for (i=0; ilinked_file->inum == inum) { - to_add->linked_file->fd_refs++; //increment the number of references - to_add->linked_file = table[i]->linked_file; //point to same file - to_add->permission = perm; //assign new permission - to_add->offset = 0; //restart offset from 0 - table[fd] = to_add; //add to table - return fd; - } - } - to_add->linked_file = f; - to_add->linked_file->fd_refs = 1; - to_add->permission = perm; - to_add->offset = 0; - table[fd] = to_add; //add to table - if (perm == 'a') { //append, need to move offset to very end - table[fd]->offset = table[fd]->linked_file->size; - } - return fd; -} - - -//this function can be used to delete a file from the list -//returns 0 if all ok, -1 if wrong -int delete_from_opentable(int fd) { - if (!file_is_open(fd)) { - return ERR_INVALID; //invalid entry - } - table[fd]->linked_file->fd_refs--; - if (table[fd]->linked_file->fd_refs == 0) { //free inode only if was referenced only once - kfree(table[fd]->linked_file); - } - kfree(table[fd]); //free space in table - bv_lower ((uint32_t)fd, open_table_free_list); //index is not taken anymore - return SUCCESS; -} - - -//this function checks whether the file is open or not -int file_is_open(int fd) { - if (fd<0 || fd>=SYSTEM_SIZE) { - return FALSE; - } - if (table[fd] == NULL) { - return FALSE; - } - return TRUE; -} - -//this function checks whether the file is open or not -int inode_is_open(struct inode* cur_inode) { - int i; - for(i = 0; i < SYSTEM_SIZE; i++){ - if(table[i] != NULL){ - if((table[i]->linked_file)->inum == cur_inode->inum){ - return TRUE; // file is open - } - } - } - return FALSE; -} - diff --git a/kernel/fs_aaa.txt b/kernel/fs_aaa.txt deleted file mode 100644 index 8d56e64e..00000000 --- a/kernel/fs_aaa.txt +++ /dev/null @@ -1,122 +0,0 @@ -make -C fs/cmdline -make[1]: Entering directory `/v/filer4b/v20q001/joeliven/Documents/2015sp/CS439_OS/Projects/Project_3/course_os_2/course_os/kernel/fs/cmdline' -gcc -g -c main.c -gcc -g -c fakelibs.c -gcc -g -c -I. ../fat16/file.c -o file.o -gcc -g -c -I. ../open_table.c -o open_table.o -gcc -g -c -I. ../../data_structures/bitvector.c -o bv.o -gcc -g main.o fakelibs.o file.o open_table.o bv.o -o buildfs -make[1]: Leaving directory `/v/filer4b/v20q001/joeliven/Documents/2015sp/CS439_OS/Projects/Project_3/course_os_2/course_os/kernel/fs/cmdline' -make -C ../user/hello -make[1]: Entering directory `/v/filer4b/v20q001/joeliven/Documents/2015sp/CS439_OS/Projects/Project_3/course_os_2/course_os/user/hello' -make[1]: `hello' is up to date. -make[1]: Leaving directory `/v/filer4b/v20q001/joeliven/Documents/2015sp/CS439_OS/Projects/Project_3/course_os_2/course_os/user/hello' -dd if=/dev/zero of=card.sd conv=notrunc bs=512 count=250000 -fs/cmdline/buildfs ../user/hello/ -SD Card initiallized successfully!!! -Finished initializing table... -Read: 'Hello, world!+' -Adding Makefile... -Adding hello.c... -Adding hello.o... -Adding hello... -0 -fd: 0 -qemu-system-arm -M versatilepb -sd card.sd -m 128M -nographic -kernel flash.bin -append "-load 0x410000 0x14000" - - -U-Boot 2014.10 (May 03 2015 - 17:00:52) - -DRAM: 128 MiB -WARNING: Caches not enabled -Using default environment - -In: serial -Out: serial -Err: serial -Net: SMC91111-0 -Warning: SMC91111-0 using MAC address from net device - -Warning: Your board does not use generic board. Please read -doc/README.generic-board and take action. Boards not -upgraded by the late 2014 may break or be removed. -Hit any key to stop autoboot: 2  1  0 -## Executing script at 0024f000 -## Booting kernel from Legacy Image at 00210000 ... - Image Name: - Image Type: ARM Linux Kernel Image (uncompressed) - Data Size: 67476 Bytes = 65.9 KiB - Load Address: 00010000 - Entry Point: 00010000 - Loading Kernel Image ... OK - -Starting kernel ... - -Enabling MMU... -5 -Initialized VM datastructures. -100 -first_level_pt=204000 -0x300402 -control reg: 0x2089107f -Got here -MMU enabled - -CourseOS! -Bootargs: 5 -test_vm_1 ... asdf -vm_l1pt_free_list=F0210000 -Got new vas at 0xF020000C -Stack addr: 0xFFF00000 -Created page table w/ 0xFFF00000's entry = 0x7F00402 -Hey, I'm printing! -F0200000 (FFFFBFA0) -F0204000 -F0204000 -Entry: 200402 -402 -(deref: entry at 0x200000: 0x0) -vm_l1pt_free_list=F0214000 -F020000C and F0200000 and F0200018 -ffffbf9c 24000000 -Testing shared memory... -301012 -map_shared_memory returned 0 -You should see a data abort... -DATA ABORT HANDLER -HANDLER: pc=12b60, lr=12b58, sp=ffffafc0, fp=ffffaffc -DSFR: 0x5 -603979776 -Freeing page at 24000000 -F0301000 F0302000 -PASSES -There are 31742 free frames. -There are 31742 free frames. -test_prq_1 ... PASSES -test_prq_2 ... PASSES -test_prq_3 ... PASSES -test_prq_4 ... PASSES -test_prq_5 ... PASSES -test_prq_6 ... PASSES - -SD card ready for transfer -SD Card initiallized successfully!!! -Finished initializing table... -test_fs_1 ... file descriptor is: 1 - -Opening file... -file descriptor is: 0 - -Writing string to file... - -Opening previous file... -0 - -Reading from file... -Read 39 bytes from file. -the buffer is: 'Hello, world I'm testing right now...! -' -PASSES -done parsing atag list -QEMU: Terminated - \ No newline at end of file diff --git a/kernel/hw_handlers.c b/kernel/hw_handlers.c deleted file mode 100644 index 20afe775..00000000 --- a/kernel/hw_handlers.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * - * Harware Handler Interface - * - */ -#include "hw_handlers.h" -#include "mmap.h" -#include "memory.h" -#include "interrupt.h" -#include "klibc.h" -#include "vm.h" -#include "fs/file.h" -#include "process.h" - -/* copy vector table from wherever QEMU loads the kernel to 0x00 */ -void init_vector_table(void) -{ - /* This doesn't seem to work well with virtual memory; reverting - * to old method. - extern uint32_t vector_table_start, vector_table_end; - uint32_t *src = &vector_table_start; - uint32_t *dst = (uint32_t *) HIVECTABLE; - - while(src < &vector_table_end) - *dst++ = *src++; - */ - - /* Primary Vector Table */ - mmio_write(0x00, BRANCH_INSTRUCTION); - mmio_write(0x04, BRANCH_INSTRUCTION); - mmio_write(0x08, BRANCH_INSTRUCTION); - mmio_write(0x0C, BRANCH_INSTRUCTION); - mmio_write(0x10, BRANCH_INSTRUCTION); - mmio_write(0x14, BRANCH_INSTRUCTION); - mmio_write(0x18, BRANCH_INSTRUCTION); - mmio_write(0x1C, BRANCH_INSTRUCTION); - - /* Secondary Vector Table */ - mmio_write(0x20, &reset_handler); - mmio_write(0x24, &undef_instruction_handler); - mmio_write(0x28, &software_interrupt_handler); - mmio_write(0x2C, &prefetch_abort_handler); - mmio_write(0x30, &data_abort_handler); - mmio_write(0x34, &reserved_handler); - mmio_write(0x38, &irq_handler); - mmio_write(0x3C, &fiq_handler); - -} - -/* handlers */ -void reset_handler(void) -{ - os_printf("RESET HANDLER\n"); - _Reset(); -} - -void __attribute__((interrupt("UNDEF"))) undef_instruction_handler(void) -{ - int spsr, lr; - - asm volatile("mrs %0, spsr" : "=r"(spsr)); - asm volatile("mov %0, lr" : "=r" (lr)); - - os_printf("UNDEFINED INSTRUCTION HANDLER\n"); - - int thumb = spsr & 0x20; - int pc = thumb ? lr - 0x2 : lr - 0x4; - - int copro = (*(int*)pc & 0xf00000) >> 24; - - if (spsr & 0x20) { - os_printf("THUMB mode\n"); - } else { - os_printf("ARM mode\n"); - } - if (spsr & 0x1000000) { - os_printf("JAZELLE enabled\n"); - } - - os_printf("COPRO: %x\n", copro); - os_printf("violating instruction (at %x): %x\n", pc, *((int*) pc)); - if (pc >= V_KERNBASE && pc < V_KERNTOP) - { - os_printf("(instruction is in kernel address range)\n"); - } - - panic(); -} - -long __attribute__((interrupt("SWI"))) software_interrupt_handler(void) -{ - int callNumber = 0, r0 = 0, r1 = 0, r2 = 0, r3 = 0; - - asm volatile ("MOV %0, r7":"=r"(callNumber)::); - asm volatile ("MOV %0, r0":"=r"(r0)::); - asm volatile ("MOV %0, r1":"=r"(r1)::); - asm volatile ("MOV %0, r2":"=r"(r2)::); - asm volatile ("MOV %0, r3":"=r"(r3)::); - - os_printf("SOFTWARE INTERRUPT HANDLER\n"); - - // Print out syscall # for debug purposes - os_printf("Syscall #: "); - os_printf("%d\n", callNumber); - os_printf("arg0=%d\n", r0); - os_printf("arg1=%d\n", r1); - os_printf("arg2=%d\n", r2); - os_printf("arg3=%d\n", r3); - os_printf("\n"); - - // System Call Handler - switch (callNumber) - { - case SYSCALL_EXIT: - // TODO: remove current process from scheduler - for (;;); - break; - case SYSCALL_DUMMY: - return 0L; - - break; - case SYSCALL_CREATE: - os_printf("Create system call called!\n"); - - return (long) kcreate((char*) r0, r1, 0); - case SYSCALL_DELETE: - os_printf("Delete system call called!\n"); - - return (long) kdelete((char*) r0, 1); - case SYSCALL_OPEN: - os_printf("Open system call called!\n"); - - return (long) kopen((char*) r0, r1); - case SYSCALL_MKDIR: - os_printf("Mkdir system call called!\n"); - - return (long) kcreate((char*) r0, 'w', 1); - case SYSCALL_READ: - os_printf("Read system call called!\n"); - - return (long) kread(r0, (void*) r1, r2); - case SYSCALL_WRITE: - os_printf("Write system call called!\n"); - - return (long) kwrite(r0, (void*) r1, r2); - case SYSCALL_CLOSE: - os_printf("Close system call called!\n"); - - return (long) kclose(r0); - case SYSCALL_SEEK: - os_printf("Seek system call called!\n"); - - return (long) kseek(r0, r1); - case SYSCALL_COPY: - os_printf("Copy system call called!\n"); - - return (long) kcopy((char*) r0, (char*) r1, r2); - case SYSCALL_LS: - os_printf("Ls system call called!\n"); - - return (long) kls((char*) r0); - case SYSCALL_SET_PERM: - os_printf("Set permission system call called!\n"); - os_printf("Yet to be implemented\n"); - return -1; - case SYSCALL_MEM_MAP: - os_printf("Memory map system call called!\n"); - os_printf("Yet to be implemented\n"); - return -1; - - case SYSCALL_MALLOC: - os_printf("malloc system call called!\n"); - - void *ptr = umalloc(r0); - - os_printf("malloc is about to return %x\n", ptr); - - return (long) ptr; - case SYSCALL_ALIGNED_ALLOC: - os_printf("aligned_alloc system call called!\n"); - void *ptr2 = ualigned_alloc(r0, r1); - - os_printf("ualigned_alloc is about to return %x\n", ptr2); - - return (long) ptr2; - case SYSCALL_FREE: - os_printf("Free system call called!\n"); - - ufree((void*) r0); - return 0L; - case SYSCALL_PRINTF: - os_printf("Printf system call called!\n"); - - os_printf((const char*) r0); - return 0L; - default: - os_printf("That wasn't a syscall you knob!\n"); - return -1L; - } -} - -void __attribute__((interrupt("ABORT"))) prefetch_abort_handler(void) -{ - int lr; - - asm volatile("mov %0, lr" : "=r" (lr)); - - os_printf("PREFETCH ABORT HANDLER, violating address: %x\n", (lr - 4)); - - panic(); -} - -void __attribute__((interrupt("ABORT"))) data_abort_handler(void) -{ - int lr; - asm volatile("mov %0, lr" : "=r" (lr)); - int pc = lr - 8; - - int far; - asm volatile("mrc p15, 0, %0, c6, c0, 0" : "=r" (far)); - - os_printf("DATA ABORT HANDLER (Page Fault)\n"); - os_printf("faulting address: 0x%x\n", far); - if (far >= V_KDSBASE) - { - os_printf("(address is in kernel address range)\n"); - } - os_printf("violating instruction (at 0x%x): %x\n", pc, *((int*) pc)); - - // Get the DSFR - int dsfr; - asm volatile("MRC p15, 0, %0, c5, c0, 0" : "=r" (dsfr)); - //os_printf("DSFR: 0x%X\n", dsfr); - - switch (dsfr) - { - case 6: // Access bit. - // Set it to 1 so we don't get notified again. - // TODO: The eviction policy will listen to this. - *((unsigned int*) (V_L1PTBASE + 2 * PAGE_TABLE_SIZE)) |= (1 << 4); - break; - default: - break; - }; -} - -void reserved_handler(void) -{ - os_printf("RESERVED HANDLER\n"); -} - -// the attribute automatically saves and restores state -void __attribute__((interrupt("IRQ"))) irq_handler(void) -{ - - os_printf("IRQ HANDLER\n"); - int cpsr = disable_interrupt_save(IRQ); -// os_printf("disabled CSPR:%X\n",cpsr); - // Discover source of interrupt - int i = 0; - // do a straight run through the VIC_INT_STATUS to determine - // which interrupt lines need to be tended to - for (i = 0; i < MAX_NUM_INTERRUPTS; i++) - { - // is the line active? - if ((1 << i) & mmio_read(VIC_IRQ_STATUS)) - { - // activate that specific handler - handle_irq_interrupt(i); - } - } - // we've gone through the VIC and handled all active interrupts - restore_proc_status(cpsr); - - enable_interrupt(IRQ_MASK); - -} - -void __attribute__((interrupt("FIQ"))) fiq_handler(void) -{ - os_printf("FIQ HANDLER\n"); - - int cpsr = disable_interrupt_save(FIQ); - - int i = 0; - // do a straight run through the VIC_INT_STATUS to determine - // which interrupt lines need to be tended to - for (i = 0; i < MAX_NUM_INTERRUPTS; i++) - { - // is the line active? - if ((1 << i) & mmio_read(VIC_FIQ_STATUS)) - { - // activate that specific handler - handle_irq_interrupt(i); - } - } - -// FIQ handler returns from the interrupt by executing: -// SUBS PC, R14_fiq, #4 - - restore_proc_status(cpsr); -} diff --git a/kernel/include/.DS_Store b/kernel/include/.DS_Store deleted file mode 100644 index b0f47a7f..00000000 Binary files a/kernel/include/.DS_Store and /dev/null differ diff --git a/kernel/include/allocator.h b/kernel/include/allocator.h deleted file mode 100644 index 27059e6d..00000000 --- a/kernel/include/allocator.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - Log - 4/2: Adjusted bump allocation algorithm: Sean V, Faseeh A, John G, Taylor S - 4/7: Fixed mem_alloc again works properly: Sean V, Faseeh A, Taylor S. - - */ -#ifndef __ALLOCATOR_H__ -#define __ALLOCATOR_H__ - -#include -#include - -#define MEM_START 0x500000 - -typedef uint32_t (*heap_extend_handler)(uint32_t amount); - -typedef struct alloc_handle { - uint32_t *heap; - uint32_t heap_size; - heap_extend_handler extend_handler; -} alloc_handle; - -alloc_handle* alloc_create(uint32_t * heap, uint32_t size, - heap_extend_handler extend_handler); -alloc_handle* alloc_create_fixed(uint32_t * buffer, uint32_t buffer_size); -void* alloc_allocate(alloc_handle * allocator, uint32_t size); -void alloc_deallocate(alloc_handle* allocator, void* ptr); -uint32_t* alloc_get_heap(alloc_handle* allocator); -uint32_t alloc_get_heap_size(alloc_handle* allocator); -int alloc_check(alloc_handle* allocator); - -#endif diff --git a/kernel/include/argparse.h b/kernel/include/argparse.h deleted file mode 100644 index 7225ebae..00000000 --- a/kernel/include/argparse.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef __ARGPARSE_H__ -#define __ARGPARSE_H__ - - - -#define ATAG_NONE 0x00000000 -#define ATAG_CORE 0x54410001 - -struct atag_core { - uint32_t flags; - uint32_t pagesize; - uint32_t rootdev; -}; - -#define ATAG_MEM 0x54410002 - -struct atag_mem { - uint32_t size; - uint32_t start; -}; - -#define ATAG_VIDEOTEXT 0x54410003 -#define ATAG_RAMDISK 0x54410004 -#define ATAG_INITRD2 0x54420005 -#define ATAG_SERIAL 0x54410006 -#define ATAG_REVISION 0x54410007 -#define ATAG_VIDEOLFB 0x54410008 -#define ATAG_CMDLINE 0x54410009 - -struct atag_cmdline { - char cmdline[1]; -}; - -struct atag_header { - uint32_t size; - uint32_t tag; -}; - -struct atag { - struct atag_header header; - union { - struct atag_core core; - struct atag_mem mem; - struct atag_cmdline cmdline; - } content; -}; - -static inline struct atag *atag_next_header(struct atag *t) -{ - return (struct atag*) ((uint32_t*)(t) + t->header.size); -} - -#define atag_iterator(tag, addr) struct atag* tag = (struct atag*) addr; tag->header.tag != ATAG_NONE; tag = atag_next_header(tag) - -void atag_print(struct atag *t); - -void argparse_process(uint32_t *p_bootargs); -void parse_arguments(int argc, char **argv); -int analyze_arguments(char **argv); -char* read_cmdline_tag(uint32_t *tag_base); -char** split_string(char *line, char **list); -int number_of_words(char *line); -int string_to_unsigned_int(char *input, int base); -int hex_value_of_character(char c); - -#endif diff --git a/kernel/include/bits/stdint.h b/kernel/include/bits/stdint.h deleted file mode 100644 index d1b27121..00000000 --- a/kernel/include/bits/stdint.h +++ /dev/null @@ -1,20 +0,0 @@ -typedef int32_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef uint32_t uint_fast16_t; -typedef uint32_t uint_fast32_t; - -#define INT_FAST16_MIN INT32_MIN -#define INT_FAST32_MIN INT32_MIN - -#define INT_FAST16_MAX INT32_MAX -#define INT_FAST32_MAX INT32_MAX - -#define UINT_FAST16_MAX UINT32_MAX -#define UINT_FAST32_MAX UINT32_MAX - -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX -#define PTRDIFF_MIN INT32_MIN -#define PTRDIFF_MAX INT32_MAX -#define SIZE_MAX UINT32_MAX diff --git a/kernel/include/data_structures/array_list.h b/kernel/include/data_structures/array_list.h deleted file mode 100644 index dc655603..00000000 --- a/kernel/include/data_structures/array_list.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * array_list.h - * - * Created on: Apr 21, 2015 - * Author: namaz89 - */ - -#ifndef KERNEL_INCLUDE_ARRAY_LIST_H_ -#define KERNEL_INCLUDE_ARRAY_LIST_H_ - -#include "data_structures/linked_list.h" -#include "klibc.h" - -#define DEFAULT_BUCKET_SIZE 20 - -typedef struct arrl_handle arrl_handle; - -struct arrl_handle { - llist_handle * linked_list; - int bucket_size; - int size; - int capacity; -}; - -arrl_handle* arrl_create(); -arrl_handle* arrl_create_fixed(uint32_t bucket_size); -void arrl_append(arrl_handle* arrl, void* elem); -void arrl_remove(arrl_handle* arrl, void* elem); -void arrl_remove_all(arrl_handle* arrl, void* elem); -uint32_t arrl_contains(arrl_handle* arrl, void* elem); -uint32_t arrl_index_of(arrl_handle* arrl, void* elem); -uint32_t arrl_count(arrl_handle* arrl); - -#endif /* KERNEL_INCLUDE_ARRAY_LIST_H_ */ diff --git a/kernel/include/data_structures/bin_tree.h b/kernel/include/data_structures/bin_tree.h deleted file mode 100644 index 7827df5c..00000000 --- a/kernel/include/data_structures/bin_tree.h +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************** - * bin_tree.h - * - * Author: Brandon Olivier // any collaborators, please add name - * - * Date: 19 April 2014 - * - * Purpose: Provide basis for b-trees for addresses - * - ********************************************************************/ - -#ifndef __b_tree_ -#define __b_tree_ - -typedef struct tree tree; -typedef struct node node; - -struct tree -{ - node *root; - int size; - int depth; -}; - -struct node -{ - node *left; - node *right; - void *address; -}; - -tree* init_tree(); -void llist_insert(tree* t, void *d); -void delete(tree *t, node *n); - -#endif diff --git a/kernel/include/data_structures/bitvector.h b/kernel/include/data_structures/bitvector.h deleted file mode 100644 index 20f2d330..00000000 --- a/kernel/include/data_structures/bitvector.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef BITVECTOR_H_ -#define BITVECTOR_H_ - -#include - -typedef struct bit_vector { - uint32_t length; - uint32_t *vector; - uint32_t actualLength; -} bit_vector; - -/* creates butvector of "size" number of bits */ -bit_vector *make_vector(uint32_t size); - -/* gets the value of bit number "index" */ -int32_t bv_get(uint32_t index, bit_vector* bit_vec); - -/* flips the bit number "index" */ -int32_t bv_toggle(uint32_t index, bit_vector* bit_vec); - -/* sets the value of bit number "index" to 1 (meaning taken) */ -int32_t bv_set(uint32_t index, bit_vector* bit_vec); - -/* sets the value of bit number "index" to 0 (meaning free) */ -int32_t bv_lower(uint32_t index, bit_vector* bit_vec); - -/* returns the first free index (first 0 in the vector) */ -int32_t bv_firstFree(bit_vector* bit_vec); - -/* frees the memory used by the vector */ -int32_t bv_free(bit_vector* bit_vec); - -/* returns whether the given index is free - Noel*/ -int32_t bv_isfree(uint32_t index, bit_vector* bit_vec); - -/* transfer a bit_vector to disk */ -int32_t bv_serialize(bit_vector* bit_vec, uint32_t start_block, uint32_t end_block); - -/* transfer a bit_vector from disk */ -int32_t bv_unserialize(bit_vector* bit_vec, uint32_t start_block, uint32_t end_block); - -#endif diff --git a/kernel/include/data_structures/hash_map.h b/kernel/include/data_structures/hash_map.h deleted file mode 100644 index f55b8a0b..00000000 --- a/kernel/include/data_structures/hash_map.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * hash_map.h - * - * Created on: Apr 18, 2015 - * Author: mwkurian - */ - -#ifndef KERNEL_INCLUDE_HASH_MAP_H_ -#define KERNEL_INCLUDE_HASH_MAP_H_ - -typedef struct { - void* data; - int flags; - long key; -} hmap_entry; - -typedef struct hmap_handle { - hmap_entry* table; - long size, count; -} hmap_handle; - -hmap_handle* hmap_create(); -hmap_handle* hmap_create_fixed(int startsize); -void* hmap_get(hmap_handle* hmap, unsigned long key); -void hmap_put(hmap_handle* hmap, unsigned long key, const void* data); -void* hmap_remove(hmap_handle* hmap, unsigned long key); -long hmap_count(hmap_handle* hash); -void hmap_free(hmap_handle* hash); - -#endif /* KERNEL_INCLUDE_HASH_MAP_H_ */ diff --git a/kernel/include/data_structures/linked_list.h b/kernel/include/data_structures/linked_list.h deleted file mode 100644 index 913cc18a..00000000 --- a/kernel/include/data_structures/linked_list.h +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************** - * linked_list.h - * - * Author: Brandon Olivier // any collaborators, please add name - * - * Date: 14 April 2014 - * - * Purpose: Provide linked lists for CourseOS - * This header provides function skeletons - * for linked_list.c - * - ********************************************************************/ - -#ifndef __llist_h -#define __llist_h - -typedef struct llist_node llist_node; - -struct llist_node { - llist_node *next; - void *data; -}; - -typedef struct { - llist_node *head; - llist_node *tail; - int count; -} llist_handle; - -/* prepend (because of speed) to the list. */ -llist_handle* llist_create(void *data); -llist_node* create_node(void *data); -void llist_free(llist_handle *l); -void llist_free_node(llist_node *node); -void llist_insert(llist_handle *l, void *data, int index); -void llist_enqueue(llist_handle *l, void *data); -void* llist_dequeue(llist_handle *l); -void llist_remove_at(llist_handle *l, int index); -void* llist_get_by_index(llist_handle *l, int index); -llist_node* llist_get_node(llist_handle *l, int index); -void llist_set_data(llist_node *l, void *data); -int llist_count(llist_handle *l); - -#endif diff --git a/kernel/include/data_structures/ring_buffer.h b/kernel/include/data_structures/ring_buffer.h deleted file mode 100644 index 7687d580..00000000 --- a/kernel/include/data_structures/ring_buffer.h +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************** - * ring_buffer.h - * - * Author: Brandon Olivier // any collaborators, please add name - * - * Date: 14 April 2014 - * - * Purpose: Provide ring buffer for CourseOS - * Data gets PUT in at the head index - * and it is GET at the tail index - * - ********************************************************************/ -#include "mem_alloc.h" - -typedef struct rb_node rb_node; -typedef struct ring_buffer ring_buffer; - -struct rb_node -{ - rb_node *next; - rb_node *prev; - void *data; -}; - -struct ring_buffer -{ - rb_node *head; - rb_node *tail; - int size; - int size_limit; -}; -ring_buffer* create(int size); -void free_ring_buffer(ring_buffer *r); - -int put(ring_buffer *r, void *data); -rb_node* get(ring_buffer *r); -void clear(ring_buffer *r); -ring_buffer* increase_size(ring_buffer *r, int by); // as in increase by x diff --git a/kernel/include/drivers/clock.h b/kernel/include/drivers/clock.h deleted file mode 100644 index 817bbc98..00000000 --- a/kernel/include/drivers/clock.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef CLOCK_H -#define CLOCK_H - -#include -#include "../../include/mmap.h" - -#endif diff --git a/kernel/include/drivers/timer.h b/kernel/include/drivers/timer.h deleted file mode 100644 index 60fac356..00000000 --- a/kernel/include/drivers/timer.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef TIMER_H -#define TIMER_H - -#include - -typedef struct { - uint32_t timer_load_value; // read/write - uint32_t timer_actual_value; // read only - uint32_t control; // read/write - uint32_t interrupt_clear; // write only - uint32_t interrupt_status; // read only - uint32_t masked_interrupt_status; // read only - uint32_t background_timer_load_value; // read/write -} rasp_pi_timer; - -_Static_assert (sizeof (rasp_pi_timer) == 28, "rasp_pi_timer check"); - -void initialize_timers(); -int set_load_value(int timer_index, int value); -int set_background_load_value(int timer_index, int value); -int clear_interupt(int timer_index); -int set_32_bit_mode(int timer_index); -int get_current_timer_value(int timer_index); -int set_periodic_mode(int timer_index); -int set_free_running_mode(int timer_index); -int start_timer(int timer_index); -int set_prescale(int timer_index, int mode); -int start_timer_interrupts( int timer_index, int star_val); -int conversion(int timer_index, int milliseconds); -int enable_timer_interrupt(int timer_index); -int disable_timer(int timer_index); -int register_handler(int timer_index, void (*handler)(void *args)); -int unregister_handler(int timer_index); - - -#endif diff --git a/kernel/include/drivers/uart.h b/kernel/include/drivers/uart.h deleted file mode 100644 index 2de2a439..00000000 --- a/kernel/include/drivers/uart.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef UART_H -#define UART_H - -void print_uart0(const char *); - -#endif // ifndef UART_H diff --git a/kernel/include/elf.h b/kernel/include/elf.h deleted file mode 100644 index 710047b2..00000000 --- a/kernel/include/elf.h +++ /dev/null @@ -1,153 +0,0 @@ -/* Any confusion with what does what can be gotten from the - following website. It defines all the values - http://man7.org/linux/man-pages/man5/elf.5.html -*/ - -#ifndef _ELF_H_ -#define _ELF_H_ - -#include -#include "klibc.h" - -typedef uint32_t Elf_Addr; // Program Address -typedef uint16_t Elf_Half; // 16 bit -typedef uint32_t Elf_Off; // File Offset -typedef int32_t Elf_Sword; // Signed 32 bit int -typedef uint32_t Elf_Word; // Unsigned 32 bit int -#define EI_NIDENT 16 - -/* Elf Header */ -/* Note: The ELF Header should begin the following header - EI_MAG0 = 0x7f - EI_MAG1 = 'E' - EI_MAG2 = 'L' - EI_MAG3 = 'F' -*/ - -/* Magic Numbers and preliminary info about file */ -#define EI_MAG0 0 // 0x7f -#define EI_MAG1 1 // 'E' -#define EI_MAG2 2 // 'L' -#define EI_MAG3 3 // 'F' -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_OSABI 7 // Targeted operating system -#define EI_ABIVERSION 8 - -/* ELF Header Flags */ -#define EF_ARM_ABIMASK 0xFF000000 -#define EF_ARM_BE8 0x00800000 -#define EF_ARM_GCCMASK 0x00400FFF -#define EF_ARM_ABI_FLOAT_HARD 0x00000400 -#define EF_ARM_ABI_FLOAT_SOFT 0x00000200 - -/* Defines what type of file it is */ -#define no_file_type 0 -#define relocatable 1 -#define executable 2 -#define shared_obj 3 -#define core 4 - -/* Types of Program Headers */ -#define PT_NULL 0 // Indicates an unused program header -#define PT_LOAD 1 // Indicates that this program header describes a segment to be loaded from the file. -#define PT_DYNAMIC 2 // Indicates a segment where dynamic linking information can be found. -#define PT_INTERP 3 // Indicates a segment where the name of the program interpreter may be found. -#define PT_NOTE 4 // Indicates a segment holding note information. -#define PT_SHLIB 5 // A reserved program header type, defined but not specified by the ELF ABI. -#define PT_PHDR 6 // Indicates a segment where the program headers may be found. - -/* Program Flags */ -// 0: No access -// 1: Just execute -// 2: Write only -// 3: Write, execute only -// 4: Read only -// 5: Read, execute only -// 6: Read, write only -// 7: Read, Write, and Execute - -typedef enum {TEXT, RODATA, DATA, SYMTAB, STRTAB, SHSTRTAB, BSS, COMMENT} Section; - -typedef struct { - unsigned char e_ident[EI_NIDENT]; // How to interpret file - Elf_Half e_type; - Elf_Half e_machine; - Elf_Word e_version; - Elf_Addr e_entry; - Elf_Off e_phoff; - Elf_Off e_shoff; - Elf_Word e_flags; - Elf_Half e_ehsize; - Elf_Half e_phentsize; - Elf_Half e_phnum; - Elf_Half e_shentsize; - Elf_Half e_shnum; - Elf_Half e_shstrndx; -}Elf_Ehdr; - -/* Program header */ -typedef struct { - Elf_Word p_type; - Elf_Off p_offset; - Elf_Addr p_vaddr; - Elf_Addr p_paddr; - Elf_Word p_filesz; - Elf_Word p_memsz; - Elf_Word p_flags; - Elf_Word p_align; -}Elf_Phdr; - -/* Section header */ -typedef struct { - Elf_Word sh_name; - Elf_Word sh_type; - Elf_Word sh_flags; - Elf_Addr sh_addr; - Elf_Off sh_offset; - Section sh_numname; - Elf_Word sh_size; - Elf_Word sh_link; - Elf_Word sh_info; - Elf_Word sh_addralign; - Elf_Word sh_entsize; -}Elf_Shdr; - -/* Symbol Table */ -typedef struct { - Elf_Word st_name; - Elf_Addr st_value; - Elf_Word st_size; - unsigned char st_info; - unsigned char st_other; - Elf_Half st_shndx; -}Elf_Sym; - -/* Relocation without addend */ -typedef struct { - Elf_Addr r_offset; - Elf_Word r_info; -}Elf_Rel; - -/* Relocation with addend */ -typedef struct { - Elf_Addr r_offset; - Elf_Word r_info; - Elf_Sword r_addend; -}Elf_Rela; - -/* Dynmaic Section header */ -typedef struct { - Elf_Sword d_tag; - union { - Elf_Word d_val; - Elf_Addr d_ptr; - }d_un; -} Elf_Dyn; - -int read_elf_header(Elf_Ehdr *h, unsigned char *pointer); -void read_program_header_table(Elf_Ehdr *eh, Elf_Phdr ph[], unsigned char *pointer); -void read_section_header_table(Elf_Ehdr *eh, Elf_Shdr sh[], uint32_t *pointer); -void parse_section_header_names(Elf_Ehdr *eh, Elf_Shdr sh[], uint32_t *pointer); -#endif diff --git a/kernel/include/fs/file.h b/kernel/include/fs/file.h deleted file mode 100644 index 078f3ebc..00000000 --- a/kernel/include/fs/file.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef __FILE_H__ -#define __FILE_H__ - -#include "global_defs.h" -#include "data_structures/bitvector.h" -#include "data_structures/linked_list.h" -#include - -#define BLOCKSIZE 512 -#define MAX_NAME_LENGTH 32 -#define MAX_DATABLOCKS_PER_INODE 100 -#define DIR_ENTRY_SIZE 40 -#define MAX_NUM_INDIRECT_BLOCKS 20 -#define MAX_DATABLOCKS_PER_INDIRECT_BLOCK ((BLOCKSIZE/4)-2) -#define MAX_DIR_ENTRIES_PER_DATA_BLOCK ((int)((BLOCKSIZE-4)/DIR_ENTRY_SIZE)-2) - - -//error codes used in return: -#define ERR_GEN -1 //general error -#define ERR_FULL -2 //error signaling end of resources -#define ERR_INVALID -3 //invalid parameter -#define ERR_404 -4 //file not found -#define ERR_SD -5 //sd card error -#define ERR_PERM -6 //permission error -#define SUCCESS 0 //no error - - -//IMPORTANT!! --------------------------------------------------------------------------------------------------- -//all constants are in units of block NUMBER | -//the indexes of arrays are also in units of block NUMBER relative to the starting offset of their cathegory. | -//--------------------------------------------------------------------------------------------------------------- - -//constants of file system, that wil be filled at boot time -struct superblock -{ - // char* fs_name; // 32 bytes (max length for this field abides by MAX_NAME_LENGTH) - int fs_version; // 36 bytes - int magic_num; // 40 bytes - int sd_card_capacity; // 44 bytes - int block_size; // 48 bytes - int root_inum; // 52 bytes - int max_inodes; // 56 bytes - int inode_size; - int max_data_blocks; // 66 bytes - int inode_bitmap_loc; // 70 bytes - int data_bitmap_loc; // 74 bytes - // int indirect_blocks_bitmap_loc; // - int start_inode_table_loc; // 78 bytes - int start_data_blocks_loc; // 82 bytes, start_inode_table_loc + 200 b/c 200 inode bl - // int start_indirect_block_table_loc; // - // int max_indirect_blocks; - // char spaceholder[???]; Might need this to make the cast from memory to superblock work...not sure??? Don't think we need this, but not sure - // the rest of the superblock will be empty for now (BLOCKSIZE - 82 = 512 - 82 = 430 free/wasted bytes) -}; - -//metadata of each file or directory -struct inode { - int inum; //inum of the file (4bytes) - int fd_refs; //how many times the file is referenced (=appears in the opentable) (4bytes) - int size; // size of the whole file (4 bytes) - int is_dir; // 1 if this is a directory, 0 if this is a file (4 bytes) - int usr_id; // id of the user who created the file (4 bytes) ...not yet used! - int direct_blocks_in_file; // how many direct block are being used (4 bytes) - int data_blocks[MAX_DATABLOCKS_PER_INODE]; // array of data (now long 70) - int indirect_blocks_in_file; // how many indirect block are being used (4 bytes) - int indirect_blocks[MAX_NUM_INDIRECT_BLOCKS]; // 50*4 = 200 bytes ....50 indirect blocks right now - bit_vector* perms; // permissions of the file (4 bytes) -}; - -struct indirect_block // total size is 1 block -{ - int block_num; - int blocks_in_file; //blocks actually used - int data_blocks[MAX_DATABLOCKS_PER_INDIRECT_BLOCK]; // because this is just an array of ints, so it's BLOCKSIZE/4 bytes bc each int is 4 bytes -}; - -struct dir_entry -{ - int inum; - int name_length; //including null terminating string - char name[MAX_NAME_LENGTH]; // 32 chars right now -}; // 8 _ MAX_NAME_LENGTH bytes long...40 bytes right now - -struct dir_data_block -{ - int block_num; - int num_entries; - struct dir_entry dir_entries[MAX_DIR_ENTRIES_PER_DATA_BLOCK]; -}; - -struct data_block -{ - char data[BLOCKSIZE]; -}; - -struct dir_helper //used by helper functions in file.c -{ - int dir_levels; - char* truncated_path; - char* last; -}; - -struct stats //statistics about the file -{ - int size; //size of the file - int fd_refs; //how many times it is open now - int is_dir; //is this a directory -}; - -int kopen(const char* filepath, const char mode); //opens the file of filepath with permissions mode -int kread(int fd, void* buf, int numBytes); //reads the open file corresponding to fd -int kwrite(int fd, void* buf, int num_bytes); //writes the open file corresponding to fd -int kclose(int fd); //closes the cpen file corresponding to fd -int kseek(int fd, int num_bytes); //moves the offset of the open file fd -int kdelete(const char* filepath, int recursive); //deletes the file or directory following filepath -int kcreate(const char* filepath, const char mode, int is_this_a_dir); //creates and opens a file or directory with permissions mode in fielpath -int kcopy(const char* source, const char* dest, const char mode); //copies the contents of a file -int kls(const char* filepath); //shows contents of one directory -int kfs_init(int inode_table_cache_size, int data_block_table_cache_size, int reformat); // initialize the filesystem: -int kfs_shutdown(); - -// // ------------------------------------------------------------------------------------------------------------------------------------------------------- -// /* HELPER FUNCTIONS */ -int get_stats(const char * filepath, struct stats * result); - -int kdelete_single_helper(struct inode * cur_inode); - -//delete the file or directory at filepath. Return -1 if the file does not exist -int kdelete_single(struct inode* cur_inode, struct inode* level_up_inode); - -/* deletes a single dir_entry */ -int kremove_dir_entry (struct inode* cur_inode, int tgt_inum); - -//from the index, gets the corresponding indirect block, either from cache or from disk -void get_indirect_block(struct inode* cur_inode, int index, struct indirect_block* cur_indirect_block); - -//from the inum, gets corresponding inode, either from cache or disk -void get_inode(int inum, struct inode* result_inode); - -//gets the inum of nextpath (file or dir) looking at the direct data blocks of cur_inode -int get_inum_from_direct_data_block(struct inode* cur_inode, const char * next_path); - -//gets the inum of netxpath (file or dir) looking at the indirect data blocks of cur_inode -int get_inum_from_indirect_data_block(struct inode * cur_inode, const char * next_path); - -//finds the inode (will be result_inode) following filepath, going dir_levels down the path, starting from starting_inum -int kfind_inode(const char* filepath, int starting_inum, int dir_levels, struct inode* result_inode); - -//finds the name of the directory path (result->truncated_path) and the name of the ending part (result->last) and the number of levels (result->levels) -//result has to be kmalloc-ed by and kfree-d by whoever calls this functinos. Also remember to free last and truncated_path. -void kfind_dir(const char* filepath, struct dir_helper* result); - -//transmits or receives the data block bitvector or the inode bitvecotr to and from disk -// First parameter: TRANSMIT or RECEIVE (defined) -// Second paramter: put pointer to bitvector (example: data_block_bitmap for data, inode_bitmap for inodes) -// Third parameter: put where that bitvecotr starts in memory (example: FS->data_bitmap_loc for data, FS->inode_bitmap_loc for inode) -// Fourth parameter: how many there are (example: FS->max_data_blocks for data, FS->max_inodes for inodes) -// index = index you would put in the bitvector -// all = 0 for only one index, 1 for all the bitvector -int transmit_receive_bitmap(int t_or_r, bit_vector* vec, int starting_loc, int max, int bit_index, int all); - -/* Helper function to add a new dir_entry to a directory file and optinally write it out to disk. - Updates the last data block of the cur_inode (directory) to add a dir_entry that stores the mapping of the new inode to its inum */ -int add_dir_entry(struct inode* cur_inode, int free_inode_loc, struct dir_helper* result); - -int get_block_address(struct inode *file_inode, int block_num); - -// Helper function for kread(): -int read_partial_block(struct inode *c_inode, int offset, void* buf_offset, int bytes_left, void* transfer_space); - -// Helper function for kread(): -int read_full_block(struct inode *c_inode, int offset, void* buf_offset, int bytesLeft, void* transfer_space);; - -int read_inode(struct inode *c_inode, int offset, void* buf, int num_bytes); - - -#endif diff --git a/kernel/include/fs/open_table.h b/kernel/include/fs/open_table.h deleted file mode 100644 index 3262cf9b..00000000 --- a/kernel/include/fs/open_table.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef __OPEN_TABLE_H__ -#define __OPEN_TABLE_H__ - -//header for the open table file -//that implements the open table for the file system -//please use provided functinos to add/remove items - -#include "global_defs.h" -#include "klibc.h" -#include "fs/file.h" -#include "data_structures/bitvector.h" - -#define SYSTEM_SIZE 512 //how many files can be open at the same time - -// Each cell of the array is a struct with infos about the file. -// More fields can be added if necessary. -struct file_descriptor { - char permission; - struct inode* linked_file; //pointer to inode struct - int offset; //keeps track of where we are reading -}; - -// Array of open files -struct file_descriptor** table; - -//list of free indexes -bit_vector * open_table_free_list; - - -void fs_table_init(); //initializes fs open table at boot up time -void fs_table_shutdown(); //closes the open table at shutdown time - -int add_to_opentable(struct inode* f, char perm); //adds a file to the opentable, returns fd if successful and -1 if not - -int delete_from_opentable(int fd); //deletes a file from the opentable, returns 0 if successful, -1 if not - -int file_is_open(int fd); //checks if there is an entry corrensponding to that fd - -int inode_is_open(struct inode* cur_inode); - -struct file_descriptor* get_descriptor(int fd); //returns the filedescriptor struct linked to fd - -#endif diff --git a/kernel/include/global_defs.h b/kernel/include/global_defs.h deleted file mode 100644 index ad90d0a6..00000000 --- a/kernel/include/global_defs.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _GLOBAL_DEFS_H_ -#define _GLOBAL_DEFS_H_ - -#include - -#define TRUE 1 -#define FALSE 0 - -#ifndef NULL -#define NULL ((void*) 0) -#endif - -typedef char *String; -typedef short Boolean; - -#ifndef __HOST -typedef uint32_t size_t; -#endif - -#define UNUSED(x) (void)(x) - -#define NBBY 8 - -#define STATUS_OK 0 -#define STATUS_FAIL -1 - -#define TEST_OK 0 -#define TEST_FAIL -1 - -#endif //defined _GLOBAL_DEFS_H_ diff --git a/kernel/include/hw_handlers.h b/kernel/include/hw_handlers.h deleted file mode 100644 index 432f71b9..00000000 --- a/kernel/include/hw_handlers.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef __HW_HANDLERS_H__ -#define __HW_HANDLERS_H__ - -/* - * - * Hardware Handler Interface for course_os - * - * - * A bit of background: - * - The ARM architecture has 7 modes of operation: - * + USR - user mode - * + FIQ - processing "fast" interrupts - * + IRQ - processing "normal" interrupts - * + SVC - proctected mode for OS - * + UND - processing an undefined instruction exception - * + SYS - also protecteed mode for OS --if anyone wants to clarify, feel free-- - * These modes can be entered or exited by modifying the CPSR (status register) - * - * exceptions (e.g. software interrupts, system calls, etc.), Interrupts (IRQ, FIQ) - * trigger the core to switch to an appropriate mode and the pc to jump to a - * preset address (somewhere in the vector table) for a branch instruction to the - * proper handler. - * - * When this happens the state of the machine must be preserved. The HW handler interface - * centralizes the 'top half' exception/interrupt handling code and takes care of the dirty low-level - * work so that the software handling interfaces for interrupts, system calls, and exceptions - * can be written more clearly elsewhere. - * - * tl;dr - write your handlers as a separate module and call them from one - * of the prototypes below. - * - */ -#include - -#define BRANCH_INSTRUCTION 0xe59ff018 // ldr pc, pc+offset - -// System Call Types -#define SYSCALL_CREATE 0 -#define SYSCALL_SWITCH 1 -#define SYSCALL_DELETE 2 -#define SYSCALL_OPEN 3 -#define SYSCALL_READ 4 -#define SYSCALL_WRITE 5 -#define SYSCALL_CLOSE 6 -#define SYSCALL_SET_PERM 7 -#define SYSCALL_MEM_MAP 8 -#define SYSCALL_SEEK 9 -#define SYSCALL_MKDIR 10 -#define SYSCALL_COPY 11 -#define SYSCALL_LS 12 -#define SYSCALL_MALLOC 13 -#define SYSCALL_ALIGNED_ALLOC 14 -#define SYSCALL_FREE 15 -#define SYSCALL_PRINTF 16 -#define SYSCALL_DUMMY 99 -#define SYSCALL_EXIT 100 -#define SYSCALL_WRITEV 101 -#define SYSCALL_PAUSE 102 - -void init_vector_table(void); - -// vector table handlers, should be loaded at 0x00 in this order! -extern void _Reset(); -void reset_handler(void); -void __attribute__((interrupt("UNDEF"))) undef_instruction_handler(void); // 0x04 -long __attribute__((interrupt("SWI"))) software_interrupt_handler(void); // 0x08 -void __attribute__((interrupt("ABORT"))) prefetch_abort_handler(void); // 0x0c -void __attribute__((interrupt("ABORT"))) data_abort_handler(void); // 0x10 -void reserved_handler(void); // 0x14 -void __attribute__((interrupt("IRQ"))) irq_handler(void); // 0x18 -void __attribute__((interrupt("FIQ"))) fiq_handler(void); // 0x1c - - -#endif diff --git a/kernel/include/interrupt.h b/kernel/include/interrupt.h deleted file mode 100644 index bd304a32..00000000 --- a/kernel/include/interrupt.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef __INTERRUPT_H__ -#define __INTERRUPT_H__ -/* - * - * Interrupt handler for course_os - * - * - * - ARM has two interrupt lines to the core: FIQ (fast interrupt), IRQ (normal interrupt) - * - Our VIC multiplexes intterupts and feeds them to the processor as either FIQ or IRQ - * Basic interrupt control flow (no vectored interrupts, no nested interrupts) is as follows: - * Interrupt Occurs -> Core branches to FIQ or IRQ vector -> vector branches to hanlder \ - * handler interfaces with VIC to determine source of interrupt -> branch to service routine \ - * - */ - -#include -#include "mmap.h" - -// general syscall function -extern int syscall(int number); - -// the VIC has 32 bits to indicate a type of interrupt -// currently we just pull a bit off the VIC and jump to that number handler -// in the handler array -// this may need to be expanded if we use the secondary controller -#define MAX_NUM_INTERRUPTS 32 - -typedef enum -{ - IRQ_MASK, // (this is bit 0x8 on the CPSR) - FIQ_MASK, // (this is bit 0x4 on the CPSR) - ALL_INTERRUPT_MASK -} interrupt_t; - -extern interrupt_t IRQ; -extern interrupt_t FIQ; -extern interrupt_t ALL; - -// this will tell if an interrupt mapping is an FIQ -// HIGH bits are FIQs -// extern char check_if_fiq[MAX_NUM_INTERRUPTS]; - -typedef struct interrupt_handler_t -{ - void (*handler)(void *args); -// more may need to be added -} interrupt_handler_t; - -/* these are what you should use to effect an - interrupt status change! */ - -#define enable_irq() \ - enable_interrupt(IRQ) -#define enable_fiq() \ - enable_interrupt(FIQ) -#define enable_interrupts() \ - enable_interrupt(ALL) -#define disable_irq() \ - disable_interrupt(IRQ) -#define disable_fiq() \ - disable_interrupt(FIQ) -#define disable_irq_save() \ - disable_interrupt_save(IRQ) -#define disable_fiq_save() \ - disable_interrupt_save(FIQ) -#define disable_interrupts() \ - disable_interrupt(ALL); -#define disable_interrupts_save() \ - disable_interrupt_save(ALL); - -/* functions (e.g. passing a bad parameter), so we'll - refer to the macros above for adjusting specific interrupt status */ -void enable_interrupt(interrupt_t); -int enable_interrupt_save(interrupt_t); - -void disable_interrupt(interrupt_t); -int disable_interrupt_save(interrupt_t); - -int get_proc_status(void); -void restore_proc_status(int); - -int register_interrupt_handler(int, interrupt_handler_t *); -void handle_irq_interrupt(int); - -/* VIC Interrupt Mappings */ -#define VIC_IRQ_STATUS PIC_ADDRESS // status of pending irqs after masking (R) -#define VIC_FIQ_STATUS (((volatile uint32_t *)(PIC_ADDRESS+0x004))) // status of pending fiqs after masking (R) -#define VIC_RAW_STATUS (((volatile uint32_t *)(PIC_ADDRESS+0x008))) // pending irqs before masking by enable register (R) -#define VIC_INT_SELECT (((volatile uint32_t *)(PIC_ADDRESS+0x00C))) // select whether source generates an IRQ or FIQ (R/W) -#define VIC_INT_ENABLE (((volatile uint32_t *)(PIC_ADDRESS+0x010))) // actually enable interrupt lines (1 = YES) (R/W) -#define VIC_INT_ENCLEAR (((volatile uint32_t *)(PIC_ADDRESS+0x014))) // clear enabled lines in VICINTENABLE (1=clear) -//#define VIC_VECT_ADDR (*((volatile uint32_t *)(PIC_ADDRESS=0x030))) // the ISR of the currently active interrupt - -// these should be used in conjunction with the bit shift mappings below -#define hw_interrupt_enable(n) mmio_write(VIC_INT_ENABLE, mmio_read(VIC_INT_ENABLE) | (1 << n)) -#define hw_interrupt_disable(n) mmio_write(VIC_INT_ENCLEAR, (1 << n)); -#define vic_select_fiq(n) mmio_write(VIC_INT_SELECT, (1 << n)); - -// Primary Interrupt Controller (PIC) -#define WATCHDOG_IRQ 0 /* watchdog controller */ -#define SWI_IRQ 1 /* software interrupt */ -#define COMMS_RX_IRQ 2 /* debug comms receive intercept */ -#define COMMS_TX_IRQ 3 /* debug comms transmit intercept */ -#define TIMER_A_IRQ 4 /* timer 0 or 1 */ -#define TIMER_B_IRQ 5 /* timer 2 or 3 */ -#define GPIO_A_IRQ 6 /* GPIO 0 */ -#define GPIO_B_IRQ 7 /* GPIO 1 */ -#define GPIO_C_IRQ 8 /* GPIO 2 */ -#define GPIO_D_IRQ 9 /* GPIO 3 */ -#define RTC_IRQ 10 /* Real Time Clock (RTC) */ -#define SSP_IRQ 11 /* synchronous serial port */ -#define UART0_IRQ 12 /* UART 0 */ -#define UART1_IRQ 13 /* UART 1 */ -#define UART2_IRQ 14 /* UART 2 */ -#define SCIO_IRQ 15 /* smart card interface */ -#define CLCD_IRQ 16 /* CLCD controller */ -#define DMA_IRQ 17 /* DMA controller */ -#define PWRFAIL_IRQ 18 /* power failure from FPGA */ -#define MBX_IRQ 19 /* graphics processor */ -// IRQ 20 is reserved by the architecture -#define VICINTSOURCE_21 21 /* external interrupt signal from DiskOnChip flash device */ -#define VICINTSOURCE_22 22 /* external interrupt signal from MCIO A */ -// IRQ 23 is reserved by the architecture -#define VICINTSOURCE_24 23 /* external interrupt signal from AACI */ -#define VICINTSOURCE_25 24 /* Ethernet */ -#define VICINTSOURCE_26 25 /* USB */ -#define VICINTSOURCE_27 26 /* external interrupt signal from expansion connector */ -#define VICINTSOURCE_28 27 /* external interrupt signal from expansion connector */ -// IRQ 29 is reserved by the architecture -// IRQ 30 is reserved by the architecture -#define VICINTSOURCE_31 31 /* secondary interrupt controller (SIC) */ - -#endif //__INTERRUPT_H__ diff --git a/kernel/include/klibc.h b/kernel/include/klibc.h deleted file mode 100644 index f46061e0..00000000 --- a/kernel/include/klibc.h +++ /dev/null @@ -1,161 +0,0 @@ -/******************************************************************** - * libc.h - * - * (Any collaborators, please add your name) - * Author: Jared McArthur, Taylor Smith, Sheldon Sandbekkhaug, Kaelen Haag - * - * Last edited: 20 April 2014 - * - * Purpose: Provide basic libc funtionality for CourseOS - * This header provides function skeletons - * for libc.c - * - * Usage: Compile into kernel. Adaptations of normal libc functions - * can be used by prepending os_ suffix. - ********************************************************************/ - -/* LOG: - * 3/30 added os_printf function - Taylor Smith - * 4/1 working more on os_printf - Taylor Smith - * 4/20 Added os_memset, os_strchrnul, os_strcpy, os_strlen, os_strtok, - * os_strspn, and os_strcspn from MUSL - Sheldon - * 4/21 Added os_memcpy for loader - Kaelen - * --------------Spring 2015--------------- - * 4/15/15: Added implementation of assert() - */ -#ifndef __KLIBC_H__ -#define __KLIBC_H__ - -#include -#include -#include "global_defs.h" - -#ifndef __NO_WFI -#define SLEEP while (1) asm volatile("wfi") -#else -#define SLEEP for(;;) -#endif - -typedef unsigned int os_size_t; - -// useful macros -#define MAX(a, b) ((a) > (b) ? a : b) -#define MIN(a, b) ((a) < (b) ? a : b) - -// basic constants -#define M_E 2.71828182845904523536 -#define M_LOG2E 1.44269504088896340736 -#define M_LOG10E 0.434294481903251827651 -#define M_LN2 0.693147180559945309417 -#define M_LN10 2.30258509299404568402 -#define M_PI 3.14159265358979323846 -#define M_PI_2 1.57079632679489661923 -#define M_PI_4 0.785398163397448309616 -#define M_1_PI 0.318309886183790671538 -#define M_2_PI 0.636619772367581343076 -#define M_1_SQRTPI 0.564189583547756286948 -#define M_2_SQRTPI 1.12837916709551257390 -#define M_SQRT2 1.41421356237309504880 -#define M_SQRT_2 0.707106781186547524401 - -#define os_printf(...) printf(__VA_ARGS__) - -/* string.h type functionality for comparing strings or mem blocks */ -int os_memcmp(const void *left, const void *right, os_size_t num); -int os_strcmp(const char *left, const char *right); - - -//4-17-15: Working assert implementation - Prakash -#define assert(X){\ - if ( (X) || _assert_fail(__FILE__, __LINE__, #X));\ -} - -/** - * Note: os_printf is restricted to printing only 256 characters. - * Supported format string conversions: - * X: upper-case hexadecimal print. - * x: lower-case hexadecimal print. - * d: signed integer. - * u: unsigned integer. - * c: ASCII character. - * s: string. - * %: the percent sign itself. - * - * Supported options: - * 0: zero-pad the result (applies to X,x,d,u). For example: - * os_printf("'%05d %05d %05u'\n", 15, -15, -15); - * prints '00015 -0015 4294967281' - */ -int os_vsnprintf(char *buf, int buflen, const char *str_buf, va_list args); -int os_snprintf(char *buf, int buflen, const char *fmt_string, ...); -int os_printf(const char *str_buf, ...); - -void *os_memset(void *dest, char c, os_size_t n); -char *__strchrnul(const char *s, char c); -char *os_strcpy(char *dest, const char *src); -char *os_strncpy(char *dest, const char *src, os_size_t n); -os_size_t os_strlen(const char *s); -char *os_strtok(char *s, const char *sep); -os_size_t os_strspn(const char *s, const char *accept); -os_size_t os_strcspn(const char *s, const char *reject); - -void os_memcpy(uint32_t * source, uint32_t * dest, os_size_t size); -/* TODO: create print function for kernel debugging purposes */ - -void* kmalloc(uint32_t size); -void* kmalloc_aligned(uint32_t size, uint32_t alignment); -void kfree(void* ptr); -uint32_t km_size(); -uint32_t kmcheck(); - -/** - * umalloc allocates memory on the user heap - * - * @param size of the block of memory allocated - * @param uint32_t size - * @return returns a pointer to the allocated block of memory - */ -void* umalloc(uint32_t size); //does user level malloc work - -/** - * ualigned alloc allocates memory on the user heap - * according to a specified alignemnt - * - * @param size of the block of memory allocated, and alignment desired - * @param uint32_t size, uint32_alignment - * @return returns a pointer to the allocated block of memory - * that is a multiple of the specified allignement - */ -void* ualigned_alloc(uint32_t size, uint32_t alignment); //does user level aligned_alloc work - -/** - * free's an allocated block of memory on the heap - * - * @param pointer to a block of memeory on the heap - * @param void* ptr - * @return nothing returned - */ -void ufree(void*); //does user level free work - -int32_t abs(int32_t); -unsigned int rand(); - -// as the codebase grows, it is important to use these macros -// so that we can filter out unnecessary messages esp. during -// development -#define LOG_LEVEL 5 - -#define DEBUG(...) if(LOG_LEVEL >= 5) os_printf(__VA_ARGS__) -#define LOG(...) if(LOG_LEVEL >= 4) os_printf(__VA_ARGS__) -#define INFO(...) if(LOG_LEVEL >= 3) os_printf(__VA_ARGS__) -#define WARN(...) if(LOG_LEVEL >= 2) os_printf(__VA_ARGS__) -#define ERROR(...) if(LOG_LEVEL >= 1) os_printf(__VA_ARGS__) - -//4-17-15: Initial panic * assert_fail functions added -void panic(); -int _assert_fail(char *_file, unsigned int _line, char *_func); - //__attribute__ ((__noreturn__)); - -void splash(void); - -#endif diff --git a/kernel/include/kthread.h b/kernel/include/kthread.h deleted file mode 100644 index a7efd61f..00000000 --- a/kernel/include/kthread.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * kthread.h - * - * Created on: Apr 23, 2015 - * Author: mwkurian - */ - -#ifndef KERNEL_INCLUDE_KTHREAD_H_ -#define KERNEL_INCLUDE_KTHREAD_H_ - -typedef void (*kthread_callback_handler)(); - -typedef struct kthread_handle { - uint32_t parent_pid; - int niceness; - int state; - kthread_callback_handler cb_handler; -} kthread_handle; - - - -#endif /* KERNEL_INCLUDE_KTHREAD_H_ */ diff --git a/kernel/include/loader.h b/kernel/include/loader.h deleted file mode 100644 index 79e38fc5..00000000 --- a/kernel/include/loader.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __loader_h -#define __loader_h -#include "global_defs.h" -#include "elf.h" -#include "process.h" - -#define USER_PROC_STACK_SIZE 0x100000 //1 MB -#define KERNEL_PROC_STACK_SIZE 0x1000 //4K -#define USER_PROC_HEAP_SIZE 4096 -#define PADDING 0x1000 - -Elf_Ehdr* load_file(pcb *, uint32_t *); //Needs to be of the type that's where ever our beginning of file is in mem - -#endif diff --git a/kernel/include/mem_alloc.h b/kernel/include/mem_alloc.h deleted file mode 100644 index 45358d11..00000000 --- a/kernel/include/mem_alloc.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -Log -4/2: Adjusted bump allocation algorithm: Sean V, Faseeh A, John G, Taylor S -4/7: Fixed mem_alloc again works properly: Sean V, Faseeh A, Taylor S. - -*/ -#ifndef __MEM_ALLOC_H__ -#define __MEM_ALLOC_H__ - -#include "allocator.h" -#include -#include - -#define MEM_START 0x500000 -#define PROC_START 0x90000000 - - -uint32_t init_heap(); -void *allocate(uint32_t, uint32_t* /*unused*/, int32_t/*unused*/); -void deallocate(void*, uint32_t*/*unused*/, int32_t/*unused*/); - -/** - * Initializes a processes heap, in the same manner that the - * kernel heap is initialized - * - * @param pointer to virtual address space (the process's VAS) - * @param struct vas* vas - * @return returns status code (for error or for ok) - */ -uint32_t init_process_heap(); - -/** - * Allocates memory on the heap for a process - * - * @param size of allocated memory - * @param uint32_t size - * @return a pointer to allocated memory - */ -void *proc_allocate(uint32_t); - -/** - * Deallocates memory on the heap for a process - * - * @param pointer to allocated memory - * @param void* ptr - * @return nothing - */ -void proc_deallocate(void*); -alloc_handle* mem_get_allocator(); -int mem_check(); -uint32_t mem_get_heap_size(); - -#endif diff --git a/kernel/include/memory.h b/kernel/include/memory.h deleted file mode 100644 index 55291475..00000000 --- a/kernel/include/memory.h +++ /dev/null @@ -1,31 +0,0 @@ -//Physical location of kernel -#define P_KERNBASE 0x00010000 -#define P_KERNTOP 0x00200000 -//Virtual location of kernel -#define V_KERNBASE 0xf0000000 -#define V_KERNTOP 0xf0200000 - -//All static kernel data structures -//Total space=1MB, currently used=44kB -#define P_KDSBASE 0x07f00000 -#define P_L1PTBASE P_KERNTOP - -#define V_KDSBASE 0xfff00000 -#define V_L1PTBASE V_KERNTOP - -#define PERIPHBASE 0x10000000 -#define PERIPHTOP 0x20000000 - -#define PCIBASE 0x41000000 -#define PCITOP 0x70000000 - -//remapped physical memory for direct access -#define PMAPBASE 0xf0200000 -#define PMAPTOP 0xf7f00000 - -// Region where we use 4K pages. -#define P_4K_BASE (P_L1PTBASE+0x200000) -#define P_4K_TOP (PMAPTOP - 0xf0000000) - -//High vectors are enabled by setting V bit in the control register -#define HIVECTABLE 0xffff0000 diff --git a/kernel/include/misc_defs.h b/kernel/include/misc_defs.h deleted file mode 100644 index 40f0779b..00000000 --- a/kernel/include/misc_defs.h +++ /dev/null @@ -1,25 +0,0 @@ -#include - -/* - Contained within this file is the base addresses to many of the Rasberry Pi's peripherals, - along with definitions for some of the important offsets from these case addresses. -*/ -#define USB_BASE_ADDRESS 0x20980000 - -#define USB_MDIO_CNTL (USB_BASE_ADDRESS +0x080) // MDIO interface control -#define USB_MDIO_GEN (USB_BASE_ADDRESS + 0x084) // Datat for MDIO interface -#define USB_VBUS_DRV (USB_BASE_ADDRESS + 0x088) // Vbus and other miscellaneous controls - -// BSC stands for Broadcom Serial Controller, from the documentation, it looks like its used for HDMI -#define BSC_MASTER_0 0x20205000 -#define BSC_MASTER_1 0x20804000 -#define BSC_MASTER_2 0x20805000 -//Offsets can be used with any of the above three BSC register BSC register bases -#define BSC_CONTROL 0x0 -#define BSC_STATUS 0x4 -#define BSC_DATA_LENGTH 0x8 -#define BSC_SLAVE_ADDRESS 0xC -#define BSC_FIFO 0x10 -#define BSC_CLOCK_DIVIDER 0x14 -#define BSC_DATA_DELAY 0x18 - diff --git a/kernel/include/mmap.h b/kernel/include/mmap.h deleted file mode 100644 index 5706b161..00000000 --- a/kernel/include/mmap.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Memory Mapped I/O addresses - */ - -#ifndef __MMAP_H__ -#define __MMAP_H__ - -#define mmio_read(address) (*((volatile uint32_t *)(address))) -#define mmio_write(address, value) (*((volatile uint32_t *)(address)) = (volatile uint32_t)(value)) - -void mmap(void *p_bootargs); - -#define PIC_ADDRESS ((volatile char *const) 0x10140000) /* interrupt controller peripheral */ -#define UART0_ADDRESS (volatile uint32_t *const) 0x101f1000 /* UART 0 base address */ -#define CLOCK_ADDRESS (volatile uint32_t *const) 0x101e8000 /* RTC base address */ - -/* Physical Hardware Addresses */ -#define PERIPHERAL_BASE_PI (volatile uint32_t *const) 0x20000000 -#define PIC_ADDRESS_PI (volatile uint32_t *const) 0x2000B000 /* interrupt controller peripheral */ -#define UART0_ADDRESS_PI (volatile uint32_t *const) 0x20201000 /* UART 0 base address */ -#define CLOCK_ADDRESS_PI (volatile uint32_t *const) 0x20003000 /* RTC base address */ -#define GPIO_ADDRESS_PI (volatile uint32_t *const) 0x20200000 - -#endif // __MMAP_H_ diff --git a/kernel/include/os_setjmp.h b/kernel/include/os_setjmp.h deleted file mode 100644 index b13af54c..00000000 --- a/kernel/include/os_setjmp.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _SETJMP_H -#define _SETJMP_H - -#include - -typedef struct __jmp_buf_tag { - __jmp_buf __jb; - unsigned long __fl; - unsigned long __ss[128/sizeof(long)]; -} jmp_buf[1]; - -// typedef jmp_buf sigjmp_buf; -// int sigsetjmp (sigjmp_buf, int); -// _Noreturn void siglongjmp (sigjmp_buf, int); - -int setjmp (jmp_buf); -_Noreturn void longjmp (jmp_buf, int); - -#define setjmp setjmp -#define longjmp longjmp - -#endif diff --git a/kernel/include/pi_light.h b/kernel/include/pi_light.h deleted file mode 100644 index 0e292d66..00000000 --- a/kernel/include/pi_light.h +++ /dev/null @@ -1,8 +0,0 @@ -#include "mmap.h" - -#define GPIO_BASE 0x20200000 -#define LED_PIN 16 - -void set_up_LED(); -void light_on(); -void light_off(); \ No newline at end of file diff --git a/kernel/include/pm.h b/kernel/include/pm.h deleted file mode 100644 index c30c7e29..00000000 --- a/kernel/include/pm.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _PM_H -#define _PM_H -#include "klibc.h" -#include "global_defs.h" -#include "stdint.h" -#include "mmap.h" - -typedef struct -{ - - //CPU peripherals - uint32_t PIC; - uint32_t VFP; - uint32_t PMU; - - //registers - uint32_t R0; - uint32_t R1; - uint32_t R2; - uint32_t R3; - uint32_t R4; - uint32_t R5; - uint32_t R6; - uint32_t R7; - uint32_t R8; - uint32_t R9; - uint32_t R10; - uint32_t R11; - uint32_t R12; - uint32_t R13; - uint32_t R14; - uint32_t R15; -} cpu_state; diff --git a/kernel/include/priorityQueue.h b/kernel/include/priorityQueue.h deleted file mode 100644 index 4dd889c3..00000000 --- a/kernel/include/priorityQueue.h +++ /dev/null @@ -1,22 +0,0 @@ -#include "process.h" -#include "global_defs.h" - -#define NOT_SET -1 - -/* Data Structure: Doubly Linked List */ -typedef struct { - struct node *next; - struct node *prev; - pcb *PCB; // Pointer to the process control block - int priority; -} Node; - - -void pqueue_init(); -int pqueue_add(void *PCB, int priority); -pcb* pqueue_remove(pcb *PCB); -void pqueue_join(pcb *other_PCB); -void dispatch(pcb *PCB); -void schedule(); -void task_yield(); -Boolean is_in_queue(int pid); diff --git a/kernel/include/process.h b/kernel/include/process.h deleted file mode 100644 index c663ccf7..00000000 --- a/kernel/include/process.h +++ /dev/null @@ -1,170 +0,0 @@ -#ifndef PROCESS_H -#define PROCESS_H -#include "global_defs.h" -#include -#include "vm.h" - -/* LOG: - 3/15: Initial skeleton and comments by Josh Guan. - 3/21: More research and comments by Faseeh Akhter and Josh Guan - 3/31: Further research and beginning implementation of process initialization and creation by Faseeh Akhter, Taylor Smith, Sean Villars - 4/2: Fixed mem_alloc and began initial pcb creation by Sean Villars, Faseeh Akhter, Josh Guan, Taylor Smith - 4/7: Fixed mem_alloc and fixed pcb allocation. added a few utility functions as well. Sean V, Faseeh A, Taylor Smith - 4/9: Added some more utility functions and changed process destroy. Sean V - 4/14: Worked on save process state. Sean V, Faseeh A, Taylor Smith - 4/15: Save state inline asm works, working on saving to pcb. Taylor s - 4/16: Load state with inline asm, Sean V, Faseeh A, Taylor Smith - ******************* - a work in progress - memory boundaries? - ******************** - - process struct outline - process id data - PID -- must be unique - User ID - Group ID - parent id ? - - processor state data - pc - CPU GPRs - CPU status word - SP, FP - - process control data - location of eimage on disk - location of user process kernel stack? - - process scheduling state - priority value? - amount of time running or suspended - EFLAGs - process structuring information - process's child process ID - other related processes via their IDs - IPC info* - process privileges* - accounting info - last run?, total CPU time accumulation - what are the bare essentials for a PCB - */ -typedef enum PROCESS_STATE -{ - PROCESS_NEW, PROCESS_READY, PROCESS_RUNNING, PROCESS_BLOCKED, PROCESS_DYING -} PROCESS_STATE; - -#define MAX_PROCESSES 32 - -#define STACK_BASE 0x9f000000 -#define PROC_LOCATION 0x9ff00000 -#define STACK_SIZE (BLOCK_SIZE) -#define STACK_TOP (STACK_BASE + STACK_SIZE) -#define HEAP_BASE 0x90000000 - - -typedef struct pcb -{ - //ID data - char* name; /* for debugging purposes */ - uint32_t PID; - uint32_t starting_address; - uint32_t process_number; // is this a mapping to actual executable image? or does it describe total number of processes? - uint32_t user_id; - uint32_t group_id; - uint32_t parent_id; - uint32_t (*function)(); - uint32_t has_executed; - struct vas* stored_vas; - uint32_t start; - uint32_t len; - //CPU state data - PROCESS_STATE current_state; - - /* - * r0-r3 are the argument and scratch registers; r0-r1 are also the result registers - * r4-r8 are callee-save registers - * r9 might be a callee-save register or not (on some variants of AAPCS it is a special register) - * r10-r11 are callee-save registers - * r12-r15 are special registers - * 37 REGISTERS IN TOTAL: 31 GPRs, 6 SRs - */ - - // WE ARE GOING TO TRY TO IMPLEMENT SETJMP/LONGJMP INSTEAD OF MANUALLY DEALING WITH THESE VALUES - // uint32_t PC; - // uint32_t SP; - // uint32_t CPSR; //current prog status register - // uint32_t SPSR; //saved prog status register when execption occurs - //unbanked register - uint32_t R0; - uint32_t R1; - uint32_t R2; - uint32_t R3; - uint32_t R4; - uint32_t R5; - uint32_t R6; - uint32_t R7; - - //banked registers - uint32_t R8; - uint32_t R9; - uint32_t R10; - uint32_t R11; - uint32_t R12; - uint32_t R13; //corresponds to the SP; do we need both? - uint32_t R14; - uint32_t R15; //corresponds to the PC; do we need both? - - //Control data - //int priority_value; - //uint32_t elapsed_time; - //uint32_t EFLAG; - //uint32_t* process_relations - //uint32_t total_cpu_time; - -//CPU state data - uint32_t SPSR; - uint32_t PC; - -//Control data - int priority_value; - uint32_t elapsed_time; - uint32_t EFLAG; - uint32_t* process_relations; - - uint32_t total_cpu_time; - - void* heap_p; - -} pcb; - -/* interface - processes can - be made (initialized) - be terminated - be duplicated - be suspended - be resumed - */ - -//input -//1) address of where the program code is in memory; elf and loader -//process -//do we n eed to create the stack and the heap? -//do we need to know where the data is? -//output -//create a corresponding pcb ds - -//Init process system -void process_init(); - -//Process API - start process from elf -pcb* process_create(const char *name); -int process_execute(pcb* pcb_p); -int process_destroy(pcb* pcb_p); - -//Execution functions -void process_load_state(pcb* pcb_p) __attribute__ ((noreturn)); -void process_save_state(pcb* pcb_p); - -#endif diff --git a/kernel/include/scheduler.h b/kernel/include/scheduler.h deleted file mode 100644 index c9723229..00000000 --- a/kernel/include/scheduler.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * scheduler.h - * - * Created on: Apr 16, 2015 - * Author: mwkurian - */ - -#include "process.h" -#include "klibc.h" -#include "data_structures/priority_queue.h" -#include "data_structures/linked_list.h" -#include "data_structures/array_list.h" - -#ifndef KERNEL_INCLUDE_SCHEDULER_H_ -#define KERNEL_INCLUDE_SCHEDULER_H_ - -typedef void (*sched_callback_handler)(uint32_t src_pid, uint32_t event, char * data, int chunk_length, int remain_length); - -typedef struct sched_task { - uint32_t parent_tid; - uint32_t tid; - uint32_t state; - uint32_t type; - int niceness; - void * task; - prq_node * node; - arrl_handle * children_tids; - sched_callback_handler cb_handler; - llist_handle * message_queue; -} sched_task; - -typedef struct sched_message_chunk { - uint32_t src_pid; - int chunk_length; - int remain_length; - uint32_t event; - char * data; -} sched_message_chunk; - -uint32_t sched_init(void); -void sched_start(void); -uint32_t sched_free(); -uint32_t sched_add_task(sched_task * task); -uint32_t sched_set_niceness(uint32_t pid, uint32_t niceness); -uint32_t shed_remove_task(uint32_t pid); -uint32_t sched_get_active_pid(); -void sched_waitpid(uint32_t pid); -sched_task* sched_create_task(uint32_t* file_p, int niceness); -sched_task* sched_create_task_from_kthread(kthread_handle * kthread, int niceness); -sched_task* sched_create_task_from_process(pcb * pcb_pointer, int niceness); -sched_task* sched_get_active_task(); -uint32_t sched_post_message(uint32_t dest_pid, uint32_t event, char * data, int len); -uint32_t sched_register_callback_handler(sched_callback_handler cb_handler); -uint32_t sched_deregister_callback_handler(); - -#endif /* KERNEL_INCLUDE_SCHEDULER_H_ */ diff --git a/kernel/include/signals.h b/kernel/include/signals.h deleted file mode 100644 index 2e53203c..00000000 --- a/kernel/include/signals.h +++ /dev/null @@ -1,11 +0,0 @@ -//Contributors: Andrew Stepek, Michael Brennen, and Matthew Stromberg - -#include -#include "include/mmap.h" -#include "include/process.h" - -typedef struct signal -{ - char * type; -} sig; - diff --git a/kernel/include/stdarg.h b/kernel/include/stdarg.h deleted file mode 100644 index 60d4e2af..00000000 --- a/kernel/include/stdarg.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _STDARG_H -#define _STDARG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define __NEED_va_list - -#include - -#if __GNUC__ >= 3 -#define va_start(v,l) __builtin_va_start(v,l) -#define va_end(v) __builtin_va_end(v) -#define va_arg(v,l) __builtin_va_arg(v,l) -#define va_copy(d,s) __builtin_va_copy(d,s) -#else -#include -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/kernel/include/stdint.h b/kernel/include/stdint.h deleted file mode 100644 index ad6aaead..00000000 --- a/kernel/include/stdint.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef _STDINT_H -#define _STDINT_H - -#define __NEED_int8_t -#define __NEED_int16_t -#define __NEED_int32_t -#define __NEED_int64_t - -#define __NEED_uint8_t -#define __NEED_uint16_t -#define __NEED_uint32_t -#define __NEED_uint64_t - -#define __NEED_intptr_t -#define __NEED_uintptr_t - -#define __NEED_intmax_t -#define __NEED_uintmax_t - -#include - -typedef int8_t int_fast8_t; -typedef int64_t int_fast64_t; - -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; - -typedef uint8_t uint_fast8_t; -typedef uint64_t uint_fast64_t; - -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -#define INT8_MIN (-1-0x7f) -#define INT16_MIN (-1-0x7fff) -#define INT32_MIN (-1-0x7fffffff) -#define INT64_MIN (-1-0x7fffffffffffffff) - -#define INT8_MAX (0x7f) -#define INT16_MAX (0x7fff) -#define INT32_MAX (0x7fffffff) -#define INT64_MAX (0x7fffffffffffffff) - -#define UINT8_MAX (0xff) -#define UINT16_MAX (0xffff) -#define UINT32_MAX (0xffffffff) -#define UINT64_MAX (0xffffffffffffffff) - -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST64_MIN INT64_MIN - -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST64_MIN INT64_MIN - -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST64_MAX INT64_MAX - -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MAX INT64_MAX - -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST64_MAX UINT64_MAX - -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -#define WINT_MIN 0 -#define WINT_MAX UINT32_MAX - -#if L'\0'-1 > 0 -#define WCHAR_MAX (0xffffffffu+L'\0') -#define WCHAR_MIN (0+L'\0') -#else -#define WCHAR_MAX (0x7fffffff+L'\0') -#define WCHAR_MIN (-1-0x7fffffff+L'\0') -#endif - -#define SIG_ATOMIC_MIN INT32_MIN -#define SIG_ATOMIC_MAX INT32_MAX - -#include - -#define INT8_C(c) c -#define INT16_C(c) c -#define INT32_C(c) c - -#define UINT8_C(c) c -#define UINT16_C(c) c -#define UINT32_C(c) c ## U - -#if UINTPTR_MAX == UINT64_MAX -#define INT64_C(c) c ## L -#define UINT64_C(c) c ## UL -#define INTMAX_C(c) c ## L -#define UINTMAX_C(c) c ## UL -#else -#define INT64_C(c) c ## LL -#define UINT64_C(c) c ## ULL -#define INTMAX_C(c) c ## LL -#define UINTMAX_C(c) c ## ULL -#endif - -#endif diff --git a/kernel/include/swap_framework.h b/kernel/include/swap_framework.h deleted file mode 100644 index 9b44906c..00000000 --- a/kernel/include/swap_framework.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef __VM_SWAP_FRAMEWORK_H -#define __VM_SWAP_FRAMEWORK_H - -#include "klibc.h" -#include - -// NOTE: SWAPPING CANNOT WORK UNTIL FILESYSTEMS CAN ALLOCATE MORE THAN 16 PAGES AT A TIME -/* Contributors: Noel Negusse and Jesse Thaden - * Last Update: 05/10/15 - */ - -/* Function: swap_framework - * Purpose: To present an API for swapping pages to various swap spaces - * so that pages may be stored independently of other related operations - * - * EXAMPLE OF VIRTUAL MEMORY ID/ADDRESS FROM SWAP SPACE - * _____________________________________________________________ - * || [24 bit] SWAP SPACE OFFSET |[8 bit] SWAP SPACE # || - * ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ - * * Total: 32 Bit Address - * therefore, there are 256 possible swap spaces possible - * w/ 2^12 page entries each (Assuming 4kB pages) - */ - -#define SWAP_SPACES (1<<8) -#define PAGE_ENTRIES (1<<12) // Assuming 4kB Pages right now -#define PAGE_SIZE (1<<12) // May carry an if statement later to account for different page sis -#define COMPRESSED_SIZE 10 // The size of compressing 16MiB of data - -typedef uint32_t *(*func)(void*, uint32_t*); - -struct swap_space { - struct swap_entry *e_head; // currently only used for LZ swap -// uint16_t pages_free; - uint8_t lower_bits; // swap space ID [8-bits] -// uint16_t flags; // swp_used (1000 or 1), swp_writeok (0010 or 2) or both (0011 or 3) - uint8_t priority; // lower is better - func store_func; - func retrieve_func; -}; // Total: 14 bytes - -struct swap_entry { - uint16_t e_flags; // PRIVILEGED_RO = 1, USER_RO = 2, PRIVILEGED_RW = 4, USER_RW = - uint16_t cmp_size; // size of compressed page - void *cmp_page; // virtual address pointer used for resolving page faults; NULL = unusedi -}; // Total: 8 bytes - -static struct swap_space *holder; -static os_size_t memory_count; - - -// Swap_init initializes swap framework -void swap_init(); -//void swap_init(os_size_t); To be implemented... [specifies global page size] - - -/* store_page will store a page to media - not main memory - storage, e.g. HDD - * from the page*. ID parameter passed will change to appropriate index (i.e. return value) - * void* page -> data to be paged - * os_size_t pagesize: The size of a page in bytes, i.e. 4096 b - * uint32_t* ID -> The page ID or address - * - * Returns: A pointer to a index value (from a bit vector) in memory - * OR returns a NULL/0 on failure - */ -uint32_t store_page(void*, uint32_t*); -uint32_t store_page_LZ(void*, uint32_t*); // All LZ functions not yet working... -// uint32_t *store_page(void*, os_size_t, uint32_t*); To be implemented... (will replace) -// uint32_t *store_pageLZ(void*, os_size_t, uint32_t*); diddo - - -/* retrieve_page will retrieve the page identified the ID pointer and - * will store it back into main memory (specified by the void *page pointer) - * - * Returns: NULL on failure or simply passes back ID on success - * NOTE: Page size was set by store_page - */ -uint32_t retrieve_page(void*, uint32_t*); -uint32_t retrieve_page_LZ(void*, uint32_t*); - - -/* Returns: The total stored memory in bytes by function store_page(void*, uint32_t*) */ -os_size_t sum_stored(); - - -/* vm_swap_page will store a page from main memory (specified by void *page) - * to a swap space either on disk or a compressed block in memory - * - * Returns: The ID pointer - bit vector index - of where the swap_space was stored and - * changes the ID pointer that value as well. Returns NULL on failure - */ -uint32_t vm_swapout_page(void*, uint32_t*); // store the page -uint32_t vm_swapin_page(void*, uint32_t*); // retrieve the page - - -/* vm_register/vm_deregister will activate/deactivate a swap space and set a priority - * accordingly to it. This allows the swap spaces use as well as increasing it's efficiency - * NOTE: deregister_swap_space will always deregister the lowest priority swap space first - * - * Returns: -1 or 1 whether the swap space registeration was a failure or success, respectively - */ -int vm_register_swap_space(func, func, int, int16_t); -void vm_deregister_swap_space(uint8_t); - - -/* Resolves the page fault and updates the corresponding page table - * - * Returns: 0 if the page_fault could not be resolved - * returns the new physical address of the loaded memory - */ -uint32_t vm_page_fault_handler(void*); - - -/* vm_scan_pages will scan through all pages for the corresponding page - * to the given page - * - * Returns: The address of matching swapped page - */ -//uint32_t* vm_scan_pages(void*); - -#endif diff --git a/kernel/include/swap_fs.h b/kernel/include/swap_fs.h deleted file mode 100644 index ddd64701..00000000 --- a/kernel/include/swap_fs.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __VM_SWAP_FS_H -#define __VM_SWAP_FS_H - -#include "bitvector.h" -#include "swap_framework.h" - - -/* Last Update: 05/11/15 */ - - -bit_vector *bv_arr[SWAP_SPACES]; -// bit_vector *free_bitvector; - - -//helper function -char *generate_filename(uint8_t); - - -/* swapfs_init initializes swap file system framework for 'npages' number of pages - * - * Returns: -1 if failure, number of bytes written on success - */ -int32_t swapfs_init(int, uint8_t); - - -/* swapfs_store will store a page to media - not main memory - storage, e.g. HDD - * from the page* - * void* page -> data to be paged - * os_size_t pagesize: The size of a page in bytes, i.e. 4096 b - * uint32_t* ID -> The page ID or address - * - * Returns: The stored page's swap space ID, index OR -1 on failure - * NOTE: Relying on the changed id pointer is safer than using the output (unless - * for error checking) due to the int64_t type output - */ -int64_t swapfs_store(void*, uint32_t*, uint8_t); - - -/* swapfs_retrieve will retrieve the page identified by the ID pointer and - * will store it back into main memory (specified by the void *page pointer) - * - * Returns: -1 on failure and 1 on success - */ -int64_t swapfs_retrieve(void*, uint32_t*, uint8_t); - - -/* Returns: -1 if failure, 1 if success */ -int32_t swapfs_disable(uint8_t); - - -#endif diff --git a/kernel/include/swap_pqueue.h b/kernel/include/swap_pqueue.h deleted file mode 100644 index b2d5b406..00000000 --- a/kernel/include/swap_pqueue.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef __VM_SWAP_PQUEUE_H -#define __VM_SWAP_PQUEUE_H - -#include -#include "swap_framework.h" - - -/* Last Update: 05/10/15 */ - - -struct node{ - struct node *next; - struct swap_entry *e_head; - uint8_t lower_bits; // swap space ID [8-bits] -// uint16_t flags; // SWP_USED (1000 or 1), SWP_WRITEOK (0010 or 2) - uint8_t priority; // lower is better - func store_func; - func retrieve_func; -}; // Total: 16 bytes - -static struct node *head; -static struct node *path; //tail -static uint8_t s; - - -/* pqueue_init initializes the priority queue with a given - * swap_space type struct - */ -void pqueue_init(struct swap_space*); - - -/* pqueue_set does a deep copy of the value of the second - * struct to the front struct - */ -void pqueue_set(struct node*, struct swap_space*); - - -/* pqueue_push pushes the swap_space struct onto the proper - * index based on the priority found in the struct - */ -void pqueue_push(struct swap_space*); - - -/* pqueue_pop_front & pqueue_pop_back pops a node from the head/back of the - * pqueue_pop_front priority queue as well as freeing the given memory of the - * head/back - */ -void pqueue_pop_front(); -void pqueue_pop_back(); -void pqueue_pop_at(uint8_t); // Note: 'at' ssid not index - -/* pqueue_size returns the current size of the priority queue */ -uint8_t pqueue_size(); - - -/* pqueue_index finds the given index of the priority queue - * - * Returns: The struct of the given index in pqueue - * NOTE: THIS IS NOT THE SAME AS THE SWAP_SPACE STRUCT - */ -struct node *pqueue_index(int); - - -/* It 'peeks' at the head of the list for a specified value - * - * Returns: The specified value from the head of the list - * 0 - lower_bits - * 1 - priority - * 2 - e_head - */ -void *pqueue_peek(int); - - -/* pqueue_find finds the actual index of the swap space ID (lower_bit value) - * - * Returns: The found node specified or NULL if not found - * NOTE: THIS IS NOT THE SAME AS THE SWAP_SPACE STRUCT - */ -struct node *pqueue_find(uint8_t); - - -#endif diff --git a/kernel/include/tests.h b/kernel/include/tests.h deleted file mode 100644 index 40a07760..00000000 --- a/kernel/include/tests.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _TESTS_H_ -#define _TESTS_H_ - -#include "global_defs.h" - -// Each test consists of a descriptor and function pointer to the test function. -typedef struct Test { - char *test_name; - int (*testptr)(); -} Test; - -// Run_tests takes an array of tests which it runs and prints the results. -void run_tests(Test *test_group[], int num_tests); -void run_fs_tests(); - -int test1(); -int test2(); - -Test* create_test(char *name, int (*test_function)()); - -#endif diff --git a/kernel/include/tests/test_hash_map.h b/kernel/include/tests/test_hash_map.h deleted file mode 100644 index 4a0d4e34..00000000 --- a/kernel/include/tests/test_hash_map.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * test_hash_map.h - * - * Created on: Apr 20, 2015 - * Author: kittenRainbow - */ - -#ifndef KERNEL_INCLUDE_TESTS_TEST_HASH_MAP_H_ -#define KERNEL_INCLUDE_TESTS_TEST_HASH_MAP_H_ - -void run_hmap_tests(); - -#endif /* KERNEL_INCLUDE_TESTS_TEST_HASH_MAP_H_ */ diff --git a/kernel/include/tests/test_mem_alloc.h b/kernel/include/tests/test_mem_alloc.h deleted file mode 100644 index b7f93d17..00000000 --- a/kernel/include/tests/test_mem_alloc.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * test_hash_map.h - * - * Created on: Apr 20, 2015 - * Author: kittenRainbow - */ - -#ifndef KERNEL_INCLUDE_TESTS_TEST_MEM_ALLOC_H_ -#define KERNEL_INCLUDE_TESTS_TEST_MEM_ALLOC_H_ - -void run_mem_alloc_tests(); - -#endif /* KERNEL_INCLUDE_TESTS_TEST_MEM_ALLOC_H_ */ diff --git a/kernel/include/tests/test_priority_queue.h b/kernel/include/tests/test_priority_queue.h deleted file mode 100644 index b177d57e..00000000 --- a/kernel/include/tests/test_priority_queue.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * test_priority_queue.h - * - * Created on: Apr 16, 2015 - * Author: mwkurian - */ - -#ifndef KERNEL_INCLUDE_TESTS_TEST_PRIORITY_QUEUE_H_ -#define KERNEL_INCLUDE_TESTS_TEST_PRIORITY_QUEUE_H_ - -void run_prq_tests(); - -#endif /* KERNEL_INCLUDE_TESTS_TEST_PRIORITY_QUEUE_H_ */ diff --git a/kernel/include/tests/test_vm.h b/kernel/include/tests/test_vm.h deleted file mode 100644 index 41b2fd3c..00000000 --- a/kernel/include/tests/test_vm.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * test_vm.h - * - * Created on: Apr 23, 2015 - * Author: mwkurian - */ - -#ifndef KERNEL_INCLUDE_TESTS_TEST_VM_H_ -#define KERNEL_INCLUDE_TESTS_TEST_VM_H_ - -void run_vm_tests(); - -#endif /* KERNEL_INCLUDE_TESTS_TEST_VM_H_ */ diff --git a/kernel/include/vm.h b/kernel/include/vm.h deleted file mode 100644 index 92228d41..00000000 --- a/kernel/include/vm.h +++ /dev/null @@ -1,193 +0,0 @@ -#ifndef __VM_H -#define __VM_H 1 - -#include "memory.h" -#include -#include "klibc.h" - -//#define BLOCK_SIZE (1<<20) -#define BLOCK_SIZE (1<<12) - -#define PAGE_TABLE_SIZE (1<<14) -#define L2_PAGE_TABLE_SIZE (1<<12) - -struct vas { - // A pointer to the first level of the pagetable. - unsigned int *l1_pagetable; - unsigned int *l1_pagetable_phys; // The physical address to it - - // A pointer to the next VAS (it's a linked list) - struct vas *next; -}; - -#define VM_ERR_BADV -1 -#define VM_ERR_BADP -2 -#define VM_ERR_MAPPED -3 -#define VM_ERR_BADPERM -4 -#define VM_ERR_UNKNOWN -5 -#define VM_ERR_NOT_MAPPED -6 - -#define KERNEL_VAS ((struct vas*)V_L1PTBASE) - -/** - * These permissions dictate who can access what pages. Note that you - * cannot combine these arbitrarily. For example: - * VM_PERM_PRIVILEGED_RO|VM_PERM_PRIVILEGED_RW - * makes no sense. If the user mode is granted a given permission, then the - * privileged mode is granted that permission as well, unless there is a - * confliction. Some examples: - * VM_PERM_USER_RO - * grants RO status to both user and privileged modes. - * - * VM_PERM_USER_RO|VM_PERM_PRIVILEGED_RW - * grants RO to the user, and RW to privileged modes. - * - * VM_PERM_USER_RW|VM_PERM_PRIVILEGED_RO - * doesn't make sense. USER_RW grants RW to both user and privileged, but - * PRIVILEGED_RO contradicts the USER_RW's implied grant. - * - * VM_ERR_BADPERM is returned if a bad permission is passed. Note that 0 - * is a valid permission, indicating that nobody may have access. - * - * (RO stands for Read-Only, RW for Read-Write) - */ -#define VM_PERM_PRIVILEGED_RO 1 -#define VM_PERM_USER_RO 2 -#define VM_PERM_PRIVILEGED_RW 4 -#define VM_PERM_USER_RW 8 - -void vm_init(); - -/** - * vm_allocate_page and vm_free_page allocate and free pages, and allow the - * VAS to access them at the given virtual address (vptr). - * Note that you cannot call free_page on a virtual address that was - * mapped using set_mapping. - * Return values: - * 0 - success - * VM_ERR_BADV - vptr was not a multiple of BLOCK_SIZE. - * VM_ERR_MAPPED - vptr is already mapped in this VAS. - * VM_ERR_BADPERM - permission is not valid (see above). - * - * free_page return values: - * 0 - success - * VM_ERR_BADV - vptr was not a multiple of BLOCK_SIZE. - * VM_ERR_MAPPED - vptr was mapped using set_mapping, not allocate_page. - * VM_ERR_NOT_MAPPED - vptr is not mapped in this VAS. - */ -int vm_allocate_page(struct vas *vas, void *vptr, int permission); -void *vm_allocate_pages(struct vas *vas, void *vptr, uint32_t nbytes, int permission); -int vm_free_page(struct vas *vas, void *vptr); - -/** - * vm_pin and vm_unpin currently do nothing. However, in the future, they will - * prevent pages from being swapped out of physical memory. - * Return values: - * 0 - Success. - */ -int vm_pin(struct vas *vas, void *vptr); -int vm_unpin(struct vas *vas, void *vptr); - -/** - * vm_set_mapping maps the given vptr to the given pptr. - * Return values: - * 0 - success - * VM_ERR_BADV - vptr was not a multiple of BLOCK_SIZE. - * VM_ERR_BADP - pptr was not a multiple of BLOCK_SIZE. - * VM_ERR_MAPPED - vptr is already mapped in this VAS. - * VM_ERR_BADPERM - permission is not valid. - * - * vm_free_mapping unmaps the vptr. Note that you may not call free_mapping - * on a virtual address that was allocated using allocate_page. - * Return values: - * 0 - success - * VM_ERR_BADV - vptr was not a multiple of BLOCK_SIZE. - * VM_ERR_NOT_MAPPED - vptr was not mapped using set_mapping. - */ -int vm_set_mapping(struct vas *vas, void *vptr, void *pptr, int permission); -int vm_free_mapping(struct vas *vas, void *vptr); - - -/* vm_swap_free_mapping is the spapping frameworks flavor on vm's vm_free_mapping - * It takes in an extra paramter that will be set to the L2 page entry (instead of 0) - * - Noel Negusse - * - * Returns: Same as vm_free_mapping - */ -int vm_swap_free_mapping(struct vas*, void*, uint32_t*); - - -/** - * Will make the memory that accessible to other_vas at other_ptr - * accessible to vas at this_ptr. - * It can then be unmapped from either using a typical vm_free_mapping - * or vm_free_page. The behavior of vm_free_mapping and vm_free_page - * will be made equivalent. - * For both, the behavior will be to free the frame if a frame was - * allocated (via vm_allocate_page) and the page is not shared. If the - * page is shared, then both will behave like vm_free_mapping. - * - * It is an error for other_ptr to point to an area not mapped in other_vas. - * - * For example, given vas1 and vas2: - * - * vm_allocate_page(vas2,0x10) - * vm_map_shared_memory(vas1, 0x20, vas2, 0x10) - * // Now vas1's 0x20 points to the same memory as vas2's 0x10 - * vm_free_page(vas2, 0x10) - * // Now vas1 is the sole owner of the memory at vas1's 0x20 - * vm_free_mapping(vas1, 0x20) - * // Now that frame has been freed - * - * All the pointers have to be a multiple of BLOCK_SIZE. - * - * Return values: - * 0 - success - * VM_ERR_BADV - this_ptr was not a multiple of BLOCK_SIZE. - * VM_ERR_BADP - other_ptr was not a multiple of BLOCK_SIZE. - * VM_ERR_NOT_MAPPED - other_ptr is not mapped in other_vas. - * VM_ERR_MAPPED - this_ptr is already mapped in vas. - * VM_ERR_BADPERM - permission is bad. - */ -int vm_map_shared_memory(struct vas *vas, void *this_ptr, struct vas *other_vas, void *other_ptr, int permission); - -/** - * This enabled the given VAS. - */ -void vm_enable_vas(struct vas *vas); - -/** - * Allocates a new VAS. - * - * Note that there is a limit of 4096 VASs in the system, including the - * kernel's VAS. - */ -struct vas *vm_new_vas(); -int vm_free_vas(struct vas *vas); - -/** - * Retrieves a reference to the currently running VAS. - */ -struct vas *vm_get_current_vas(); - -/** - * Switches to the kernel's VAS. - */ -void vm_use_kernel_vas(); - -static inline void ensure_kernel_vas() -{ - assert (vm_get_current_vas() == KERNEL_VAS && "Must run in kernel VAS!"); -} - -void vm_test(); - -static inline void vm_invalidate_tlb(void) -{ - // Invalidate the TLB - asm volatile("mcr p15, 0, %[r], c8, c5, 0" : : [r] "r" (0x0)); - asm volatile("mcr p15, 0, %[r], c8, c6, 0" : : [r] "r" (0x0)); - asm volatile("mcr p15, 0, %[r], c8, c7, 0" : : [r] "r" (0x0)); -} - -#endif diff --git a/kernel/interrupt.c b/kernel/interrupt.c deleted file mode 100644 index c33d1c2a..00000000 --- a/kernel/interrupt.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * - * Interrupts - * - */ -#include "interrupt.h" -#include "klibc.h" -#include "drivers/timer.h" - -// there are 32 kinds of interrupts on the VIC -// this structure may need to be expanded if the secondary controller is incorporated -static interrupt_handler_t *handlers[MAX_NUM_INTERRUPTS]; - -static int initialized; - -// holds defined fiq interrupts -static int check_if_fiq[MAX_NUM_INTERRUPTS]; - -// define interrupt types -interrupt_t IRQ = IRQ_MASK; -interrupt_t FIQ = FIQ_MASK; -interrupt_t ALL = ALL_INTERRUPT_MASK; - -// In a system with an interrupt controller, software is required to: -// determine from the interrupt controller which interrupt source is requesting service -// determine where the service routine for that interrupt source is loaded -// mask or clear that interrupt source, before re-enabling processor interrupts to permit another interrupt to be taken. - -// Interrupts must be enabled in three places: -// (1) the core (CPSR) -// (2) the VIC (interrupt controller) -// (3) (sometimes) in the device (this should be done in the device driver) - -// CLear Interrupts -// Do not disable the VIC and the CSPR is disable in the hw_hanlders -// you have to clear the interrupt from the register handler -// Look At timer.c it has a great example of it. -// Here's the Website to the VIC we are using http://infocenter.arm.com/help/topic/com.arm.doc.ddi0181e/DDI0181.pdf - -//They are three handlers you must use First is the (IRQ)interrupt handler its in hw_handlers.c (with attribute Irq) -// second is the ISR routine handler which is the one in interrupt.c -// third is the specific handler you created a great example is in the timer.c it is called timer_interrupt_handler. -// If youre having an error it must be in the third handler not the first two. - -// Setup FIQ interrupts -void init_fiqs() -{ - check_if_fiq[11] = 1; // synchronous serial port - check_if_fiq[17] = 1; // DMA controller -} - -// when you register an interrupt handler it's line will be enabled in the VIC -// telling the device itself to fire interrupts should be done in the driver -// -// also, since we don't really have a working malloc, the handler structure will -// have to be built in the driver and passed to register_ -int register_interrupt_handler(int num, interrupt_handler_t *handler) -{ - // lazy initialization - if (initialized != -1) - { - os_printf("INITIALIZING THE INTERRUPT SYSTEM\n"); - - for(int i=0; i MAX_NUM_INTERRUPTS) // bad irq number - return -1; - else if (handlers[num] != 0) - { // something has already been registered there - os_printf("Already registered\n"); - return -1; - } - else if (handler == 0) // we need a NULL macro - return -1; - - // put the handler in the array - handlers[num] = handler; - - // enable the specific interrupt in hardware on the VIC - hw_interrupt_enable(num); - - // check to see if this is an FIQ - if (check_if_fiq[num]) - // update the "select" register on the VIC - vic_select_fiq(num); - - // return a success value - return 0; -} - -// handle_interrupt takes a number (the interrupt from the VIC), looks into -// the table of registered handlers, and calls the appropriate handler -void handle_irq_interrupt(int interrupt_vector) -{ - os_printf("handling interrupt %d\n", interrupt_vector); - // go to handler routine - os_printf("Jumping to %X...\n", handlers[interrupt_vector]->handler); - handlers[interrupt_vector]->handler((void *) interrupt_vector); - -} - -/* enable IRQ and/or FIQ */ -void enable_interrupt(interrupt_t mask) -{ - get_proc_status(); - - // enable interrupt on the core - switch (mask) - { - case IRQ_MASK: - asm volatile("cpsie i"); - break; - case FIQ_MASK: - asm volatile("cpsie f"); - break; - case ALL_INTERRUPT_MASK: - asm volatile("cpsie if"); - break; - } -} - -/* disable IRQ and/or FIQ */ -void disable_interrupt(interrupt_t mask) -{ - // disable interrupts on the core - switch (mask) - { - case IRQ_MASK: - asm volatile("cpsid i"); - break; - case FIQ_MASK: - asm volatile("cpsid f"); - break; - case ALL_INTERRUPT_MASK: - asm volatile("cpsid if"); - break; - } -} - -/* disable IRQ and/or FIQ, but also return a copy of the CPSR */ -int disable_interrupt_save(interrupt_t mask) -{ - /* get a copy of the current process status register */ - int cpsr; - asm volatile("mrs %0, cpsr" : "=r"(cpsr)); - // disable interrupts on the core - switch (mask) - { - case IRQ_MASK: - asm volatile("cpsid i"); - break; - case FIQ_MASK: - asm volatile("cpsid f"); - break; - case ALL_INTERRUPT_MASK: - asm volatile("cpsid if"); - break; - } - return cpsr; -} - -/* return a full 32-bit copy of the current process status register */ -int get_proc_status(void) -{ - int cpsr; - asm volatile("mrs %0, cpsr" : "=r"(cpsr)); - return cpsr; -} - -/* restore control status (interrupt, mode bits) of the cpsr */ -/* (e.g. when we return from a handler, restore value from - disable_interrupt_save */ -void restore_proc_status(int cpsr) -{ - asm volatile("msr cpsr_c, %0" : : "r"(cpsr)); -} - diff --git a/kernel/kernel.ld b/kernel/kernel.ld deleted file mode 100644 index 3670ea97..00000000 --- a/kernel/kernel.ld +++ /dev/null @@ -1,13 +0,0 @@ -ENTRY(_Reset) -SECTIONS -{ - . = 0x10000; - .startup . : { startup.o(.text) } - .text : { *(.text) } - .data : { *(.data) } - .bss : { *(.bss COMMON) } - . = ALIGN(8); - . = . + 0x1000; - stack_top = .; -} - diff --git a/kernel/kernelPi.ld b/kernel/kernelPi.ld deleted file mode 100644 index 4b9b4529..00000000 --- a/kernel/kernelPi.ld +++ /dev/null @@ -1,12 +0,0 @@ -ENTRY(_Reset) -SECTIONS -{ - . = 0x8000; - .startup . : { startup.o(.text) } - .text : { *(.text) } - .data : { *(.data) } - .bss : { *(.bss COMMON) } - . = ALIGN(8); - . = . + 0x1000; - stack_top = .; -} \ No newline at end of file diff --git a/kernel/klibc.c b/kernel/klibc.c deleted file mode 100644 index 889a1dae..00000000 --- a/kernel/klibc.c +++ /dev/null @@ -1,928 +0,0 @@ -/******************************************************************** - * klibc.c - * - * (Any collaborators, please add your name) - * Author: Jared McArthur, Taylor Smith, Sheldon Sandbekkhaug, Kaelen Haag, Collin Massey - * - * Last edited: 4 December 2015 - * - * Purpose: Provide basic libc funtionality for CourseOS - * This file provides function implementations - * for skels in libc.h - * - * Usage: Compile into kernel. Adaptations of normal libc functions - * can be used by prepending os_ suffix. - * - * Notes: The following were adapted directly from musl-libc: - * memcmp, memset, strcmp, strchrnul, strcpy, strlen, strtok - ********************************************************************/ -#include -#include - -#include "klibc.h" -#include "global_defs.h" -#include "mem_alloc.h" -#include "interrupt.h" - -//FIXME: decouple -#include "drivers/uart.h" - -#define LOWER_CASE 0 -#define UPPER_CASE 1 -#define NO_CASE 2 - -// Helpers for MUSL String functions -#define UCHAR_MAX 0xFF -#define ALIGN (sizeof(os_size_t)) -#define ONES ((os_size_t)-1/UCHAR_MAX) -#define HIGHS (ONES * (UCHAR_MAX/2+1)) -#define HASZERO(x) (((x)-ONES) & (~(x)) & HIGHS) - -static char lower_case_digits[16] = "0123456789abcdef"; -static char upper_case_digits[16] = "0123456789ABCDEF"; - -/*4-17-15: - Prakash - * panic() added - - Currrently states the panic and stalls the machine - */ -void panic() -{ - disable_interrupts() - ; - //os_printf("Kernel panic!\n"); - os_printf("\n ) ( \n"); - os_printf(" ( /( ( )\\ ) \n"); - os_printf(" )\\()) ( ( ( )\\ (()/( ) ( \n"); - os_printf("|((_)\\ ))\\ )( ( ))((_) /(_)| /( ( )\\ ( \n"); - os_printf("|_ ((_)((_|()\\ )\\ ) /((_) (_)) )(_)) )\\ |(_) )\\ \n"); - os_printf("| |/ (_)) ((_)_(_/((_))| | | _ ((_)_ _(_/((_)((_) \n"); - os_printf(" ' 0) - { - for (i = 0; i < padding - ndigits - negate; i++) - { - *buf = pad_char; - buf++; - max_len--; - if (max_len == 0) - return orig_max_len; - } - } - - // Output the digits - for (i = ndigits - 1; i >= 0; i--) - { - *buf = tmp_buf[i]; - buf++; - max_len--; - if (max_len == 0) - return orig_max_len; - } - if (ndigits == 0 && padding <= 0) - { - *buf = '0'; - buf++; - max_len--; - if (max_len == 0) - return orig_max_len; - } - - return orig_max_len - max_len; -} - -// args must already have been started -int os_vsnprintf(char *buf, int buflen, const char *str_buf, va_list args) -{ - if (buflen == 0) - return 0; - buflen--; - if (buflen == 0) - { - buf[0] = 0; - return 1; - } - int nwritten = 0; - int t_arg; - char* str_arg; - int padding = -1; - char pad_char = 0; - while (*str_buf != '\0') - { - int n; - if (*str_buf == '%') - { - str_buf++; - // This label is where we go after we've read an option. - reread_switch: ; - switch (*str_buf) - { - case '0': - // Zero-padding... Read all the numbers. - // Then restart the switch statement. - padding = 0; - pad_char = '0'; - while (*str_buf <= '9' && *str_buf >= '0') - { - padding *= 10; - padding += *str_buf - '0'; - str_buf++; - } - goto reread_switch; - break; - case 'X': - t_arg = va_arg(args, int); - n = print_int(buf, buflen, t_arg, 16, 1, padding, pad_char, 1); - break; - case 'x': - t_arg = va_arg(args, int); - n = print_int(buf, buflen, t_arg, 16, 1, padding, pad_char, 0); - break; - case 'd': - t_arg = va_arg(args, int); - n = print_int(buf, buflen, t_arg, 10, 0, padding, pad_char, 0); - break; - case 'u': - t_arg = va_arg(args, int); - n = print_int(buf, buflen, t_arg, 10, 1, padding, pad_char, 0); - break; - case 'c': - t_arg = va_arg(args, int); - *buf = t_arg; - n = 1; - break; - case 's': - str_arg = va_arg(args, char*); - os_strncpy(buf, str_arg, buflen); - n = os_strlen(str_arg); - if (n > buflen) - { - n = buflen; - } - break; - case '%': - *buf = '%'; - n = 1; - break; - } - // Reset all the options - padding = -1; - } - else - { - *buf = *str_buf; - n = 1; - } - buf += n; - buflen -= n; - nwritten += n; - if (buflen <= 0) - { - //Return! - break; - } - str_buf++; - } - buf[0] = 0; - nwritten++; - - return nwritten; -} - -int os_snprintf(char *buf, int buflen, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - int n = os_vsnprintf(buf, buflen, fmt, args); - va_end(args); - return n; -} - -int os_printf(const char *str_buf, ...){ -va_list args; -va_start(args, str_buf); -char buf[256]; -int n = os_vsnprintf(buf, 255, str_buf, args); -va_end(args); -print_uart0(buf); -return n; -} - -/* Set the first n bytes of dest to be the value c.*/ -void *os_memset(void *dest, char c, os_size_t n) -{ - unsigned char *s = dest; - os_size_t k; - - /* Fill head and tail with minimal branching. Each - * conditional ensures that all the subsequently used - * offsets are well-defined and in the dest region. */ - - if (!n) - return dest; - s[0] = s[n - 1] = c; - if (n <= 2) - return dest; - s[1] = s[n - 2] = c; - s[2] = s[n - 3] = c; - if (n <= 6) - return dest; - s[3] = s[n - 4] = c; - if (n <= 8) - return dest; - - /* Advance pointer to align it at a 4-byte boundary, - * and truncate n to a multiple of 4. The previous code - * already took care of any head/tail that get cut off - * by the alignment. */ - - k = -(uintptr_t) s & 3; - s += k; - n -= k; - n &= -4; - -#ifdef __GNUC__ - typedef uint32_t __attribute__((__may_alias__)) u32; - typedef uint64_t __attribute__((__may_alias__)) u64; - - u32 c32 = ((u32) -1) / 255 * (unsigned char) c; - - /* In preparation to copy 32 bytes at a time, aligned on - * an 8-byte bounary, fill head/tail up to 28 bytes each. - * As in the initial byte-based head/tail fill, each - * conditional below ensures that the subsequent offsets - * are valid (e.g. !(n<=24) implies n>=28). */ - - *(u32 *) (s + 0) = c32; - *(u32 *) (s + n - 4) = c32; - if (n <= 8) - return dest; - *(u32 *) (s + 4) = c32; - *(u32 *) (s + 8) = c32; - *(u32 *) (s + n - 12) = c32; - *(u32 *) (s + n - 8) = c32; - if (n <= 24) - return dest; - *(u32 *) (s + 12) = c32; - *(u32 *) (s + 16) = c32; - *(u32 *) (s + 20) = c32; - *(u32 *) (s + 24) = c32; - *(u32 *) (s + n - 28) = c32; - *(u32 *) (s + n - 24) = c32; - *(u32 *) (s + n - 20) = c32; - *(u32 *) (s + n - 16) = c32; - - /* Align to a multiple of 8 so we can fill 64 bits at a time, - * and avoid writing the same bytes twice as much as is - * practical without introducing additional branching. */ - - k = 24 + ((uintptr_t) s & 4); - s += k; - n -= k; - - /* If this loop is reached, 28 tail bytes have already been - * filled, so any remainder when n drops below 32 can be - * safely ignored. */ - - u64 c64 = c32 | ((u64) c32 << 32); - for (; n >= 32; n -= 32, s += 32) - { - *(u64 *) (s + 0) = c64; - *(u64 *) (s + 8) = c64; - *(u64 *) (s + 16) = c64; - *(u64 *) (s + 24) = c64; - } -#else - /* Pure C fallback with no aliasing violations. */ - for (; n; n--, s++) *s = c; -#endif - - return dest; -} - -/* Returns a pointer to the first instance of c in s, like indexOf(). - If c is not found, then return a pointer to the NULL character at - the end of String s. - */ -char *__strchrnul(const char *s, char c) -{ - os_size_t *w, k; - - if (!c) - return (char *) s + os_strlen(s); - - for (; (uintptr_t) s % ALIGN; s++) - if (!*s || *(unsigned char *) s == c) - return (char *) s; - k = ONES * c; - for (w = (void *) s; !HASZERO(*w) && !HASZERO(*w ^ k); w++) - ; - for (s = (void *) w; *s && *(unsigned char *) s != c; s++) - ; - return (char *) s; -} - -/* Copies the String src to dest */ -char *os_strcpy(char *dest, const char *src) -{ - const unsigned char *s = (const unsigned char*) src; - unsigned char *d = (unsigned char*) dest; - while ((*d++ = *s++)) - ; - return dest; -} - -/* Copies the String src to dest */ -char *os_strncpy(char *dest, const char *src, os_size_t n) -{ - const unsigned char *s = (const unsigned char*) src; - unsigned char *d = (unsigned char*) dest; - while ((*d++ = *s++) && n--) - ; - return dest; -} - -/* Return the length of s */ -os_size_t os_strlen(const char *s) -{ - const char *a = s; - const os_size_t *w; - for (; (uintptr_t) s % ALIGN; s++) - if (!*s) - return s - a; - for (w = (const void *) s; !HASZERO(*w); w++) - ; - for (s = (const void *) w; *s; s++) - ; - return s - a; -} - -/* A re-entrant function that returns a substring of s. The substring starts - at the beginning of the string or the previous index of one of the - delimiter characters (indicated by sep). The substring ends at the next - delimeter character (indicated by sep). - */ -char *os_strtok(char *s, const char *sep) -{ - static char *p; - if (!s && !(s = p)) - return NULL; - s += os_strspn(s, sep); - if (!*s) - return p = 0; - p = s + os_strcspn(s, sep); - if (*p) - *p++ = 0; - else - p = 0; - return s; -} - -/* Returns the length of the initial segment of s that only includes - the characters in c. - */ -os_size_t os_strspn(const char *s, const char *accept) -{ - char c = s[0]; // The character in s being checked - int length = 0; - - // Check each character in s - while (c != 0) - { - Boolean ok = FALSE; - - // Check against each character in accept - int i; - for (i = 0; i < os_strlen(accept); i++) - { - if (c == accept[i]) - { - ok = TRUE; - } - } - - if (ok == TRUE) - { - // If c matched any character in accept, continue - length++; - c = s[length]; - } - else - { - // If did not match any character in accept, we are done - return length; - } - } - return length; -} - -/* Returns the length of the initial segment of s that does not contain - any characters in string c. - */ -os_size_t os_strcspn(const char *s, const char *reject) -{ - char c = s[0]; // The character in s being checked - int length = 0; - - // Check each character in s - while (c != 0) - { - // Check against each character in reject - int i; - for (i = 0; i < os_strlen(reject); i++) - { - if (c == reject[i]) - { - return length; - } - } - - // If c did not match any reject characters, continue - length++; - c = s[length]; - } - return length; -} - -int32_t abs(int32_t val) -{ - const int32_t mask = val >> sizeof(int32_t) * (NBBY - 1); - return (val + mask) ^ mask; -} - -// Return string converted to int form, or 0 if not applicable -// Necessary comments provided in atof() (next function) -int katoi(const char *string) -{ - if (!string) - return 0; - - int integer = 0; - int sign = 1; - - if (*string == '-') - { - sign = -1; - string++; - } - else if (*string == '+') - { - string++; - } - - while (*string != '\0') - { - if (*string >= '0' && *string <= '9') - { - integer *= 10; - integer += (*string - '0'); - } - else - { - return 0; - } - } - return sign * integer; -} - -// Return string converted to double form, or 0 if not applicable -double katof(const char *string) -{ - if (!string) - return 0.0; - - double integer = 0.0; // before decimal - double fraction = 0.0; // after decimal - int sign = 1; // positive or negative? - int divisor = 1; // used to push fraction past decimal point - Boolean after_decimal = FALSE; // decimal point reached? - - // Check if string includes sign (including a "+") - if (*string == '-') - { - sign = -1; - string++; // progress to next char - } - else if (*string == '+') - { - string++; - } - - while (*string != '\0') - { - if (*string >= '0' && *string <= '9') - { - if (after_decimal) - { - fraction *= 10; // progress to next position in integer - fraction += (*string - '0'); // add integer form of current number in string - divisor *= 10; - } - else - { - integer *= 10; // progress to next position in integer - integer += (*string - '0'); // add integer form of current number in string - } - } - else if (*string == '.') - { - if (after_decimal) - return 0.0; // more than one '.' - after_decimal = TRUE; - } - else - { - return 0.0; // current char in string is not a number or '.' - } - string++; - } - return sign * (integer + (fraction / divisor)); -} - -// Return string converted to long int form, or 0 if not applicable -long int katol(const char *string) -{ - return (long int) katoi(string); -} - -/* -// Same as katof, but makes endptr point to the string which comes after the number -double kstrtod(const char *string, char **endptr) -{ - if (!string) - return 0.0; - - double integer = 0.0; - double fraction = 0.0; - int sign = 1; - int divisor = 1; - Boolean after_decimal = FALSE; - Boolean result_found = FALSE; - double result = 0.0; - - if (*string == '-') - { - sign = -1; - string++; - } - else if (*string == '+') - string++; -} - -while (!result_found) -{ - if (*string >= '0' && *string <= '9') - { - if (after_decimal) - { - fraction *= 10; - fraction += (*string - '0'); - divisor *= 10; - } - else - { - integer *= 10; - integer += (*string - '0'); - } - string++; - } - else if (*string == '.') - { - if (after_decimal) - return 0.0; - after_decimal = true; - string++; - } - else - { - result = sign * (integer + (fraction/divisor)); - result_found = true; - } -} - -*endptr = string; - -return result; -} -*/ - -//Same as katol, but makes endptr point to the string which comes after the number -long int kstrtol(const char *string, char **endptr) -{ -if (!string) - return 0; - -long int integer = 0; -long int result = 0; -Boolean result_found = FALSE; -int sign = 1; - -if (*string == '-') -{ - sign = -1; - string++; -} -else if (*string == '+') -{ - string++; -} - -while (!result_found) -{ - if (*string >= '0' && *string <= '9') - { - integer *= 10; - integer += (*string - '0'); - string++; - } - else - { - result = sign * integer; - result_found = TRUE; - } -} -*endptr = (char*) string; - -return result; -} - -void *kmalloc(uint32_t size) -{ -void* block = (void*) allocate(size, 0 /* unused */, 0 /* unused */); -return block; -} - -// Allocates n * size portion of memory (set to 0) and returns it -void *kcalloc(uint32_t n, uint32_t size) -{ -uint32_t total_size = n * size; -void* block = kmalloc(total_size); - -return block ? os_memset(block, 0, total_size) : NULL; -} - -uint32_t kmcheck() -{ -return mem_check(); -} - -// NOTE potentially expand these features. offer more -// memory stats -uint32_t km_size() -{ -return mem_get_heap_size(); -} - -void* kmalloc_aligned(uint32_t size, uint32_t alignment) -{ -void* block; -void* ptr; - -switch (alignment) -{ -case 4: - block = kmalloc(size + 4); - ptr = (void*) (((uint32_t) block + 4) & ~0x3); - return ptr; -case 1024: - block = kmalloc(size + 1024); - ptr = (void*) (((uint32_t) block + 1024) & ~0x1ff); - return ptr; -case 4096: - block = kmalloc(size + 4096); - ptr = (void*) (((uint32_t) block + 4096) & ~0x7ff); - return ptr; -case 16 * 1024: - block = kmalloc(size + 16 * 1024); - ptr = (void*) (((uint32_t) block + 16 * 1024) & ~0x1fff); - return ptr; -default: - return kmalloc(size); -} -} - -void kfree(void* ptr) -{ -deallocate((uint32_t*) ptr, 0 /* unused */, 0 /* unused */); -} - -// FIXME: Implement kmalloc_size() (or something like it) -// Resize memory pointed to by ptr to new size -void *krealloc(void *ptr, uint32_t size) -{ -if (!ptr) - return kmalloc(size); - -if (size == 0) -{ - kfree(ptr); - return NULL; -} - -/* I'm not sure how to implement kmalloc_size(), - * which returns the size of the block pointed - * to by a pointer, without keeping track of - * the size of the block pointed to whenever - * kmalloc() is called, or by defining it - - uint32_t msize = kmalloc_size(ptr); - if (msize >= size) - return ptr; - - - void *new_ptr = kmalloc(size); - os_memcpy(new_ptr, ptr, msize); - return new_ptr; */ - -return ptr; -} - -unsigned int rand() -{ -static unsigned int z1 = 12345, z2 = 67891, z3 = 11121, z4 = 31415; -unsigned int b; -b = ((z1 << 6) ^ z1) >> 13; -z1 = ((z1 & 4294967294U) << 18) ^ b; -b = ((z2 << 2) ^ z2) >> 27; -z2 = ((z2 & 4294967288U) << 2) ^ b; -b = ((z3 << 13) ^ z3) >> 21; -z3 = ((z3 & 4294967280U) << 7) ^ b; -b = ((z4 << 3) ^ z4) >> 12; -z4 = ((z4 & 4294967168U) << 13) ^ b; -return (z1 ^ z2 ^ z3 ^ z4); -} - -/** - * umalloc allocates memory on the user heap - * - * @param size of the block of memory allocated - * @param uint32_t size - * @return returns a pointer to the allocated block of memory - */ -void* umalloc(uint32_t size) -{ -void* block = (void*) proc_allocate(size); -return block; -} - -/** - * ualigned alloc allocates memory on the user heap - * according to a specified alignemnt - * - * @param size of the block of memory allocated, and alignment desired - * @param uint32_t size, uint32_alignment - * @return returns a pointer to the allocated block of memory - * that is a multiple of the specified allignement - */ - -void* ualigned_alloc(uint32_t size, uint32_t alignment) -{ -void* block; -void* ptr; - -switch (alignment) -{ -case 4: - block = umalloc(size + 4); - ptr = (void*) (((uint32_t) block + 4) & ~0x3); - return ptr; -case 1024: - block = umalloc(size + 1024); - ptr = (void*) (((uint32_t) block + 1024) & ~0x1ff); - return ptr; -case 4096: - block = umalloc(size + 4096); - ptr = (void*) (((uint32_t) block + 4096) & ~0x7ff); - return ptr; -case 16 * 1024: - block = umalloc(size + 16 * 1024); - ptr = (void*) (((uint32_t) block + 16 * 1024) & ~0x1fff); - return ptr; -default: - return umalloc(size); -} -} - -/** - * free's an allocated block of memory on the heap - * - * @param pointer to a block of memeory on the heap - * @param void* ptr - * @return nothing returned - */ -void ufree(void* ptr) -{ -proc_deallocate((uint32_t*) ptr); -} diff --git a/kernel/linker/kernel.ld b/kernel/linker/kernel.ld new file mode 100644 index 00000000..6c487f28 --- /dev/null +++ b/kernel/linker/kernel.ld @@ -0,0 +1,37 @@ +ENTRY(_Reset) + +__KERNEL_VIRTUAL_OFFSET = 0x80000000; +__BOOT_ADDRESS = 0x8000; + +SECTIONS +{ + . = __BOOT_ADDRESS; + __BOOT_START = .; + .boot : { + */startup.o (.text) + */startup.o (.data) + */stacks.o (.text) + */startup.o (.bss) + } + __BOOT_END = .; + . += __KERNEL_VIRTUAL_OFFSET; + + __KERNEL_BASE = .; + .text : AT(ADDR(.text) - __KERNEL_VIRTUAL_OFFSET) { + *(EXCLUDE_FILE (*/startup.o */stacks.o) .text) + *(.rodata*) + } + + .data : AT(ADDR(.data) - __KERNEL_VIRTUAL_OFFSET){ + *(EXCLUDE_FILE (*/startup.o) .data) + } + + .bss : AT(ADDR(.bss) - __KERNEL_VIRTUAL_OFFSET) { + *(EXCLUDE_FILE (*/startup.o) COMMON) + *(EXCLUDE_FILE (*/startup.o) .bss) + } + + /*make kernel top megabyte aligned*/ + . = ALIGN(1024 * 1024); + __KERNEL_TOP = .; +} diff --git a/kernel/loader.c b/kernel/loader.c deleted file mode 100644 index 0f4ad1f7..00000000 --- a/kernel/loader.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include "loader.h" -#include "mem_alloc.h" -#include "klibc.h" -#include "process.h" -#include "elf.h" - -//Worked on by Kaelen Haag and Jeremy Wenzel -//We determine what the size of our process is going to be -//Determine the size of the segments that need to be loaded in (has p_type == PT_LOAD) -//Account for the other stuff we'll need (Stack, Heap, spacing) -os_size_t det_proc_size(Elf_Ehdr *h, Elf_Phdr ph[]) -{ - os_size_t process_size = 0; - int i = 0; - //Add up the size of all the necessary sections that - for (; i < (h->e_phnum); i++) - { - if (ph[i].p_type == PT_LOAD) - { - process_size += ph[i].p_memsz; - } - } - - process_size += USER_PROC_STACK_SIZE; - process_size += USER_PROC_HEAP_SIZE; //This is going to be the heap size (need to determine what this should be - - //Padding we want to be able to have some padding between certain sections of the program - //mainly the stack from the other parts - process_size += PADDING; - - return process_size; - -} - -//Probably want to return a memory address rather than nothing. -//Take a process control block and pointer to the start of an ELF file in memory. -Elf_Ehdr* load_file(pcb * pcb_p, uint32_t * file_pointer) -{ - Elf_Ehdr *h = (Elf_Ehdr *) kmalloc(sizeof(Elf_Ehdr)); // Get elf header - os_printf("elf header= %x\n", h); - int i = read_elf_header(h, (unsigned char *) file_pointer); - - if (i == -1) - { - os_printf("File is Not an ELF File. Exiting\n"); - return 0; - } - - if (h->e_phnum == 0) - { - os_printf("No Program headers in ELF file. Exiting\n"); - return 0; - } - - Elf_Phdr * ph = (Elf_Phdr *) kmalloc(h->e_phnum * sizeof(Elf_Phdr)); - Elf_Shdr * sh = (Elf_Shdr *) kmalloc(h->e_shnum * sizeof(Elf_Shdr)); - // FIXME: why is sh not used? - UNUSED(sh); - read_program_header_table(h, ph, (unsigned char *) file_pointer); - - //allocate pages for the read only segment - - //allocate pages for text section - - //assert(1 == 2 && "load_file"); - - //read_section_header_table(h, sh, (uint32_t*)file_pointer); - // /vm_enable_vas(pcb_p->stored_vas); - - //allocate_process_memory(pcb_p, h, ph, file_pointer); - - //vm_use_kernel_vas(); - return h; -} - diff --git a/kernel/memory/allocator.c b/kernel/memory/allocator.c deleted file mode 100644 index e665f193..00000000 --- a/kernel/memory/allocator.c +++ /dev/null @@ -1,324 +0,0 @@ -#include "global_defs.h" -#include "klibc.h" -#include "allocator.h" - -uint32_t* __alloc_extend_heap(alloc_handle*allocator, uint32_t amount); - -/* - * The kernel heap is organized in blocks. Each block has a header and a - * footer each a 4 byte integer, at the beginning and end of the block. - * The header and footer both specify the size of the block in question. - * Used blocks are indicated by the heap header and the heap footer being - * negative. - * - * To allocate a block, we start at the first block and walk through each - * one, finding the first free block large enough to support a header, - * footer, and the size requested. - * - * To free a block, we do a bunch of merging stuff to check to see if we - * should merge with the blocks on the left or right of us, respectively. - */ -alloc_handle* alloc_create(uint32_t * buffer, uint32_t buffer_size, - heap_extend_handler extend_handler) { - - if (buffer_size <= sizeof(alloc_handle)) { - return 0; - } - - alloc_handle* alloc_handle_ptr = (alloc_handle*) buffer; - - // storing the alloc_handle struct - // inside the heading of the buffer - alloc_handle_ptr->heap = ((void*) buffer) + sizeof(alloc_handle); - alloc_handle_ptr->heap_size = buffer_size - sizeof(alloc_handle); - alloc_handle_ptr->extend_handler = extend_handler; - - uint32_t* heap_header = alloc_handle_ptr->heap; - uint32_t* heap_footer = (uint32_t*) ((void*) alloc_handle_ptr->heap - + alloc_handle_ptr->heap_size - sizeof(int)); - - *heap_header = alloc_handle_ptr->heap_size - 2 * sizeof(uint32_t); - *heap_footer = alloc_handle_ptr->heap_size - 2 * sizeof(uint32_t); - - return alloc_handle_ptr; -} - -alloc_handle* alloc_create_fixed(uint32_t * buffer, uint32_t buffer_size) { - return alloc_create(buffer, buffer_size, NULL); -} - -// TODO: what if there's an error allocating the page? -// Returns a pointer to the new (big) free block's header -uint32_t* __alloc_extend_heap(alloc_handle*allocator, uint32_t amount) { - if(!allocator->extend_handler) { - return 0; - } - - uint32_t start_size = allocator->heap_size; - uint32_t amount_added = allocator->extend_handler(amount); - - if (amount_added <= 0) { - return 0; - } - - // Now extend the footer block - int32_t *orig_footer = (int32_t*) ((void*) allocator->heap + start_size - - sizeof(uint32_t)); - - allocator->heap_size += amount_added; - - // If it's free, simply move it (and update the header) - // If it's used, add a free block to the end - if (*orig_footer > 0) { - uint32_t *orig_header = (uint32_t*) ((void*) allocator->heap - + start_size - 2 * sizeof(uint32_t) - *orig_footer); - uint32_t *new_footer = (uint32_t*) ((void*) allocator->heap - + allocator->heap_size - sizeof(uint32_t)); - - *new_footer = *orig_footer + amount_added; - *orig_header += amount_added; - return orig_header; - } else { - - uint32_t *new_header = (uint32_t*) ((void*) allocator->heap + start_size); - uint32_t *new_footer = (uint32_t*) ((void*) allocator->heap - + allocator->heap_size - sizeof(uint32_t)); - *new_header = amount_added - 2 * sizeof(uint32_t); - *new_footer = amount_added - 2 * sizeof(uint32_t); - return new_header; - } - - return 0x0; -} - -void* alloc_allocate(alloc_handle * allocator, uint32_t size) { - int32_t i, ret_ptr; - - for (i = 0; i < allocator->heap_size;) { - uint32_t* header_addr = (uint32_t*) ((void*) allocator->heap + i); - int32_t header = *header_addr; - - uint32_t* footer_addr = (uint32_t*) ((void*) allocator->heap + i - + sizeof(int32_t) + size); - - //free and >= request - if (header > 0 && header >= size) { - //cannot split this block - if (header < (size + 2 * sizeof(int32_t) + sizeof(char))) { - footer_addr = (uint32_t*) ((void*) allocator->heap + i - + sizeof(int32_t) + abs(header)); - - ret_ptr = i + sizeof(int32_t); - //mark header as used - *header_addr = header * (-1); - //insert a footer at end of block - *footer_addr = header * (-1); - return (uint32_t*) ((void*) allocator->heap + ret_ptr); - - } - - //can split this block - else { - ret_ptr = i + sizeof(int32_t); - - int32_t old_space = header; - int32_t occ_space = size + 2 * sizeof(int32_t); - //mark header as used - *header_addr = size * (-1); - //insert footer - *footer_addr = size * (-1); - - //insert new free block header - uint32_t* new_header = (uint32_t*) ((void*) allocator->heap + i - + 2 * sizeof(int32_t) + size); - *new_header = old_space - occ_space; - //insert new free block footer - uint32_t* new_footer = (uint32_t*) ((void*) allocator->heap + i - + sizeof(int32_t) + old_space); - *new_footer = old_space - occ_space; - - return (uint32_t*) ((void*) allocator->heap + ret_ptr); - } - } - //jump to the next block - else { - i = i + abs(header) + 2 * sizeof(int32_t); - } - } - - // Allocate some more memory. - uint32_t new_amt = size + 2 * sizeof(uint32_t); - uint32_t *header = __alloc_extend_heap(allocator, new_amt); - - if (header == 0) { - return 0; - } - - // Recursive call. TODO: (relatively) Inefficient - return alloc_allocate(allocator, size); -} - -void alloc_deallocate(alloc_handle* allocator, void* ptr) { - uint32_t first_block = 0; - uint32_t last_block = 0; - - uint32_t* header_addr = (uint32_t*) ((void*) ptr - sizeof(int32_t)); - uint32_t size = abs(*header_addr); - - uint32_t* footer_addr = (uint32_t*) ((void*) ptr + size); - - if (header_addr == allocator->heap) { - first_block = 1; - } - - if (footer_addr + sizeof(int32_t) - == (void*) allocator->heap + allocator->heap_size) { - last_block = 1; - } - - //os_printf("Freeing %d-sized block at %X. first/last=%d/%d\n", size, header_addr, first_block,last_block); - - //only check and coalesce right block - if (first_block) { - uint32_t* right_header_addr = (uint32_t*) ((void*) footer_addr - + sizeof(int32_t)); - int32_t right_block_size = *right_header_addr; - - //free right block - if (right_block_size > 0) { - //set new header at freed blocks header - *header_addr = size + right_block_size + 2 * sizeof(int32_t); - //set new footer at right blocks footer - uint32_t* right_footer_addr = (uint32_t*) ((void*) footer_addr - + 2 * sizeof(int32_t) + right_block_size); - *right_footer_addr = size + right_block_size + 2 * sizeof(int32_t); - } else { - //make freed blocks header and footer positive - *header_addr = size; - *footer_addr = size; - } - } - - //only check and coalesce left block - if (last_block) { - uint32_t* left_block_header = (uint32_t*) ((void*) header_addr - - sizeof(int32_t)); - int32_t left_block_size = *left_block_header; - - //free left block - if (left_block_size > 0) { - //set new header at left blocks header - uint32_t* left_header_addr = (uint32_t*) ((void*) header_addr - - 2 * sizeof(int32_t) - left_block_size); - *left_header_addr = size + left_block_size + 2 * sizeof(int32_t); - //set new footer at freed blocks footer - *footer_addr = size + left_block_size + 2 * sizeof(int32_t); - } else { - *header_addr = size; - *footer_addr = size; - } - } - - //check and coalesce both adjacent blocks - if (!first_block && !last_block) { - uint32_t* right_block_header = (uint32_t*) ((void*) footer_addr - + sizeof(int32_t)); - int32_t right_block_size = *right_block_header; - - uint32_t* left_block_header = (uint32_t*) ((void*) header_addr - - sizeof(int32_t)); - int32_t left_block_size = *left_block_header; - //os_printf("left/right sizes are %d/%d, size=%d\n", left_block_size, right_block_size, size); - - //both adjacent blocks are free - if (right_block_size > 0 && left_block_size > 0) { - int32_t new_size = size + right_block_size + left_block_size - + 4 * sizeof(int32_t); - - //set new header at left blocks header - uint32_t* left_header_addr = (uint32_t*) ((void*) header_addr - - 2 * sizeof(int32_t) - left_block_size); - *left_header_addr = new_size; - //set new footer at right blocks footer - uint32_t* right_footer_addr = (uint32_t*) ((void*) footer_addr - + 2 * sizeof(int32_t) + right_block_size); - *right_footer_addr = new_size; - } - - //only right free block - else if (right_block_size > 0 && left_block_size < 0) { - //set new header at freed blocks header - *header_addr = size + right_block_size + 2 * sizeof(int32_t); - //set new footer at right blocks footer - uint32_t* right_footer_addr = (uint32_t*) ((void*) footer_addr - + 2 * sizeof(int32_t) + right_block_size); - *right_footer_addr = size + right_block_size + 2 * sizeof(int32_t); - } - //only left free block - else if (left_block_size > 0 && right_block_size < 0) { - //set new header at left blocks header - uint32_t* left_header_addr = (uint32_t*) ((void*) header_addr - - 2 * sizeof(int32_t) - left_block_size); - *left_header_addr = size + left_block_size + 2 * sizeof(int32_t); - //set new footer at freed blocks footer - *footer_addr = size + left_block_size + 2 * sizeof(int32_t); - } else { - *header_addr = size; - *footer_addr = size; - } - - } -} - -/** - * Returns 0 on success. -1 on error. - */ -int alloc_check(alloc_handle* allocator) { - char* ptr = (char*) allocator->heap; - uint32_t* end_ptr = (uint32_t*) ((void*) allocator->heap - + allocator->heap_size); - int i, block = 0; - - LOG("Checking memory...\n"); - for (i = 0; i < allocator->heap_size; i += 0) { - uint32_t* block_addr = (uint32_t*) (ptr + sizeof(int32_t)); - - uint32_t* header_addr = (uint32_t*) ptr; - int32_t block_header = *header_addr; - int32_t block_size = abs(block_header); - - uint32_t* footer_addr = (uint32_t*) (ptr + sizeof(int32_t) + block_size); - int32_t block_footer = *footer_addr; - - if (block_header == block_footer && block_header <= 0) { - LOG("Block %d Allocated:", block); - LOG("\tsize = %d, address = %x\n", block_size, block_addr); - } else if (block_header == block_footer && block_header > 0) { - LOG("Block %d Free:", block); - LOG("\tsize = %d, address = %x\n", block_size, block_addr); - } else { - ERROR("INCONSISTENT HEAP\n"); - ERROR("block_header = %d\n", block_header); - ERROR("block_footer = %d\n", block_footer); - ERROR("header addr = %x\n", header_addr); - ERROR("footer addr = %x\n", footer_addr); - return -1; - } - - ptr = ptr + block_size + 2 * sizeof(int32_t); - block++; - if ((uint32_t*) ptr == end_ptr) { - return 0; - } - } - - return 0; -} - -uint32_t* alloc_get_heap(alloc_handle* allocator) { - return allocator->heap; -} - -uint32_t alloc_get_heap_size(alloc_handle* allocator) { - return allocator->heap_size; -} diff --git a/kernel/memory/mem_alloc.c b/kernel/memory/mem_alloc.c deleted file mode 100644 index ab9a20bf..00000000 --- a/kernel/memory/mem_alloc.c +++ /dev/null @@ -1,151 +0,0 @@ -#include "klibc.h" -#include "mem_alloc.h" -#include "vm.h" -#include "allocator.h" - -uint32_t *nextBlock = (uint32_t*) MEM_START; -uint32_t buffer_size; -alloc_handle * allocator; -uint32_t __mem_extend_heap(uint32_t amt); - -alloc_handle * proc_allocator; -uint32_t proc_buffer_size; -uint32_t __mem_extend_proc_heap(uint32_t amt); - -//bump pointer allocation -void *mem_alloc(uint32_t size) -{ - uint32_t temp = size / 4; - - if ((size % 4) > 0) - { - temp++; - } - uint32_t* allocBlock = nextBlock; - nextBlock = nextBlock + size; - - return allocBlock; -} - -/* - * The kernel heap is organized in blocks. Each block has a header and a - * footer each a 4 byte integer, at the beginning and end of the block. - * The header and footer both specify the size of the block in question. - * Used blocks are indicated by the heap header and the heap footer being - * negative. - * - * To allocate a block, we start at the first block and walk through each - * one, finding the first free block large enough to support a header, - * footer, and the size requested. - * - * To free a block, we do a bunch of merging stuff to check to see if we - * should merge with the blocks on the left or right of us, respectively. - */ - -// TODO: what if there's an error allocating the page? -// Returns a pointer to the new (big) free block's header -uint32_t __mem_extend_heap(uint32_t amt) -{ - uint32_t amt_added = 0; - while (amt_added < amt) { - int retval = vm_allocate_page(KERNEL_VAS, - (void*) (MEM_START + buffer_size), VM_PERM_PRIVILEGED_RW); - if (retval) { - os_printf("ERROR: vm_allocate_page(,%d,) returned %d\n", - MEM_START + amt_added, retval); - break; - } - amt_added += BLOCK_SIZE; - buffer_size += BLOCK_SIZE; - } - - return amt_added; -} - -uint32_t init_heap() -{ - int retval = vm_allocate_page(KERNEL_VAS, (void*) MEM_START, - VM_PERM_PRIVILEGED_RW); - if (retval) { - os_printf("ERROR: vm_allocate_page returned %d\n", retval); - return STATUS_FAIL; - } - - buffer_size = BLOCK_SIZE; - allocator = alloc_create((uint32_t*) MEM_START, buffer_size, &__mem_extend_heap); - return STATUS_OK; -} - -uint32_t init_process_heap(struct vas* vas) -{ - int retval = vm_allocate_page(vas, (void*) PROC_START, VM_PERM_USER_RW); - vm_map_shared_memory(KERNEL_VAS, (void*)PROC_START, vas, (void*)PROC_START, VM_PERM_USER_RW); - if (retval) { - os_printf("ERROR: vm_allocate_page returned %d\n", retval); - return STATUS_FAIL; - } - else{ - os_printf("Page allocated for process heap at %x:\n",PROC_START); - } - - proc_buffer_size = BLOCK_SIZE; - proc_allocator = alloc_create((uint32_t*) PROC_START, proc_buffer_size, &__mem_extend_proc_heap); - vm_free_mapping(KERNEL_VAS,(void*)PROC_START); - return STATUS_OK; -} - -uint32_t __mem_extend_proc_heap(uint32_t amt) -{ - struct vas* pvas = vm_get_current_vas(); - - uint32_t amt_added = 0; - while (amt_added < amt) - { - int retval = vm_allocate_page(pvas, (void*) PROC_START, VM_PERM_USER_RW); - vm_map_shared_memory(KERNEL_VAS, (void*)PROC_START, pvas, (void*)PROC_START, VM_PERM_USER_RW); - if (retval) { - os_printf("ERROR: vm_allocate_page returned %d\n", retval); - return STATUS_FAIL; - } - else{ - os_printf("Page allocated for process heap at %x:\n",PROC_START); - } - amt_added += BLOCK_SIZE; - proc_buffer_size += BLOCK_SIZE; - } - - vm_free_mapping(KERNEL_VAS,(void*)PROC_START); - return amt_added; -} - -void* proc_allocate(uint32_t size) -{ - return alloc_allocate(proc_allocator, size); -} - -void proc_deallocate(void* ptr) -{ - return alloc_deallocate(proc_allocator, ptr); -} - -void* allocate(uint32_t size, uint32_t* heap, int32_t heap_size) -{ - return alloc_allocate(allocator, size); -} - -void deallocate(void* ptr, uint32_t* heap, int32_t heap_size) -{ - return alloc_deallocate(allocator, ptr); -} - -alloc_handle * mem_get_allocator(){ - return allocator; -} - -int mem_check(){ - return alloc_check(allocator); -} - -uint32_t mem_get_heap_size(){ - return alloc_get_heap_size(allocator); -} diff --git a/kernel/mmap.c b/kernel/mmap.c deleted file mode 100644 index ee8341ab..00000000 --- a/kernel/mmap.c +++ /dev/null @@ -1,180 +0,0 @@ -#include "mmap.h" -#include "memory.h" -#include "klibc.h" -#include "drivers/uart.h" -#include "vm.h" - -/* - * APX AP Privileged Unprivileged - * 1 11 (0x8c00) = read-only read-only - * 1 01 (0x8400) = read-only no access - * 0 10 (0x0800) = read-write read-only - * 0 01 (0x0400) = read-write no-access - * See http://infocenter.arm.com/help/topic/com.arm.doc.ddi0333h/Caceaije.html - - * Bits 0 and 1 identify the table entry type - * 0 = translation fault - * 1 = course page table - * 2 = section or supersection - */ - -int vm_build_free_frame_list(void *start, void *end); - -unsigned int * first_level_pt = (unsigned int*) P_L1PTBASE; -extern struct vm_free_list *vm_vas_free_list; -extern struct vm_free_list *vm_l1pt_free_list; -extern struct vm_free_list *vm_l2pt_free_list; - -void mmap(void *p_bootargs) -{ - //char *cmdline_args = read_cmdline_tag(p_bootargs); - //print_uart0(cmdline_args); - //print_uart0("\n"); - asm volatile("cpsid if"); - - //stash register state on the stack - asm volatile("push {r0-r11}"); - - os_printf("%X\n", p_bootargs); - - /* - int pte; - unsigned int mb_addr = 0; - for(pte = 0; pte < 4096; pte++){ - - //one-to-one mapping - first_level_pt[pte] = mb_addr | 0x0400 | 2; - mb_addr += (1024*1024); - - } - */ - //TODO:. Collin LOOOK HERE - first_level_pt = (unsigned int *) (P_L1PTBASE + PAGE_TABLE_SIZE); - //first_level_pt = 0x00200000 + 0x4000 = 0x00204000 - os_printf("first_level_pt=%X\n", first_level_pt); - - int i; - for (i = 0; i < PAGE_TABLE_SIZE >> 2; i++) - { - first_level_pt[i] = 0; - } - - //temporarily map where it is until we copy it in VAS - first_level_pt[P_KDSBASE >> 20] = P_KDSBASE | 0x0400 | 2; - //first_level_pt[0x07f00000>>20] = first_level_pt[7F] = 0x07f00000 = 0x07f04010 - // 0x00004000 - // 0x00000010 - - //1MB for static kernel data structures (stacks and l1 pt) - first_level_pt[V_KDSBASE >> 20] = P_KDSBASE | 0x0400 | 2; - //first_level_pt[0xfff00000>>20] = first_level_pt[0xfff] = 0x0x7f04010 - - //map the kernel where its currently loaded in the same location temporarily - //should be less than a MB - first_level_pt[P_KERNBASE >> 20] = 0 << 20 | 0x0400 | 2; - - //also map it to high memory at 0xf0000000 (vpn = 3840) - first_level_pt[V_KERNBASE >> 20] = 0 << 20 | 0x0400 | 2; - first_level_pt[(V_KERNBASE + 0x100000) >> 20] = 0x100000 | 0x0400 | 2; - - //map ~2MB of peripheral registers one-to-one - first_level_pt[PERIPHBASE >> 20] = PERIPHBASE | 0x0400 | 2; - first_level_pt[(PERIPHBASE + 0x100000) >> 20] = (PERIPHBASE + 0x100000) - | 0x0400 | 2; - - //map 752MB of PCI interface one-to-one - unsigned int pci_bus_addr = PCIBASE; - for (i = (PCIBASE >> 20); i < (PCITOP >> 20); i++) - { - first_level_pt[i] = pci_bus_addr | 0x0400 | 2; - pci_bus_addr += 0x100000; - } - - // Quick coarse page table address - //unsigned int coarse_page_table_address = P_L1PTBASE + 2*PAGE_TABLE_SIZE; - //os_printf("coarse pt: 0x%X\n", coarse_page_table_address); - - //remap 62MB of physical memory after the kernel - // (KERNTOP to end of physical RAM (PMAPTOP)) - // This is where we allocate frames from. Except for the first one. - unsigned int phys_addr = P_KERNTOP; - // +1 to skip L1PTBASE - for (i = (PMAPBASE >> 20); i < (PMAPTOP >> 20); i++) - { - first_level_pt[i] = phys_addr | 0x0400 | 2; - phys_addr += 0x100000; - } - - // Fill in the coarse page table - // (TODO: How do we handle 64kB pages? Do they take up 16 entries?) - //os_memset((void*)coarse_page_table_address, 0, L2_PAGE_TABLE_SIZE); - // Set the first page to phys_addr - //*(unsigned int*)coarse_page_table_address = phys_addr | 0x20 | 2; - //os_printf("0x%X\n", *(unsigned int*)coarse_page_table_address); - - first_level_pt[V_L1PTBASE >> 20] = P_L1PTBASE | 0x0400 | 2; - - // We have to empty out the first MB of that, so we can use it as an array of VASs - // The first slot is actually the kernel's VAS - ((struct vas*) P_L1PTBASE)->l1_pagetable = (unsigned int*) (V_L1PTBASE - + PAGE_TABLE_SIZE); //first_level_pt; - ((struct vas*) P_L1PTBASE)->l1_pagetable_phys = first_level_pt; - ((struct vas*) P_L1PTBASE)->next = 0x0; - vm_vas_free_list = (struct vm_free_list*) ((void*) vm_vas_free_list - + sizeof(struct vas)); - vm_l1pt_free_list = (struct vm_free_list*) ((void*) vm_l1pt_free_list - + PAGE_TABLE_SIZE); - - unsigned int pt_addr = (unsigned int) first_level_pt; - - os_printf("0x%X\n", first_level_pt[(PMAPBASE + 0x100000) >> 20]); - - //TTBR0 - asm volatile("mcr p15, 0, %[addr], c2, c0, 0" : : [addr] "r" (pt_addr)); - // Translation table 1 - //asm volatile("mcr p15, 0, %[addr], c2, c0, 1" : : [addr] "r" (pt_addr)); - //asm volatile("mcr p15, 0, %[n], c2, c0, 2" : : [n] "r" (0)); - - //Set Domain Access Control to enforce out permissions - //b01 = Client. Accesses are checked against the access permission bits in the TLB entry. - asm volatile("mcr p15, 0, %[r], c3, c0, 0" : : [r] "r" (0x1)); - - /*CONTROL REGISTER - * Enable MMU by setting 0 - * Alignment bit 1 - * D-cache bit 2 - * I-cache bit 12 - * V bit 13 (1=high vectors 0xffff0000) - * We disable high vectors, since low vectors work just fine. - */ - unsigned int control; - - //Read contents into control - asm volatile("mrc p15, 0, %[control], c1, c0, 0" : [control] "=r" (control)); - //Set bit 0,1,2,12,13 - //control |= 0x3007; //0b11000000000111 - control |= 0x1007; //0b01000000000111 (No high vectors) - control |= 1 << 23; // Enable ARMv6 - //control |= 1<<29; // Enable ForceAP - os_printf("control reg: 0x%x\n", control); - //Write back value into the register - asm volatile("mcr p15, 0, %[control], c1, c0, 0" : : [control] "r" (control)); - - os_printf("Got here\n"); - - // Build the free frame list - vm_build_free_frame_list((void*) PMAPBASE + 0x100000, (void*) PMAPTOP); //(void*)PMAPBASE+(unsigned int)((PMAPTOP)-(PMAPBASE))); - - //restore register state - asm volatile("pop {r0-r11}"); - - // Except for r0, which is p_bootargs. stacks.s needs to know it. - asm volatile("mov r0, %[args]" : : [args] "r" (p_bootargs)); - - asm volatile("cpsie if"); - asm volatile (".include \"stacks.s\""); - - //branch to proper kernel at start - asm volatile("bl start2"); - -} diff --git a/kernel/offset.sh b/kernel/offset.sh deleted file mode 100755 index 20932776..00000000 --- a/kernel/offset.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -if [ "$(uname)" == "Darwin" ]; then - printf "bootm 0x%X\n" $(expr $(stat -f%z ../u-boot/u-boot-$1/u-boot.bin) + 65536) -else - printf "bootm 0x%X\n" $(expr $(stat -c%s ../u-boot/u-boot-$1/u-boot.bin) + 65536) -fi - diff --git a/kernel/os_longjmp.s b/kernel/os_longjmp.s deleted file mode 100644 index aff15fbd..00000000 --- a/kernel/os_longjmp.s +++ /dev/null @@ -1,37 +0,0 @@ -.global _longjmp -.global longjmp -.type _longjmp,%function -.type longjmp,%function -_longjmp: -longjmp: - mov ip,r0 - movs r0,r1 - moveq r0,#1 - ldmia ip!, {v1,v2,v3,v4,v5,v6,sl,fp,sp,lr} - - adr r1,1f - ldr r2,1f - ldr r1,[r1,r2] - - tst r1,#0x260 - beq 3f - tst r1,#0x20 - beq 2f - ldc p2, cr4, [ip], #48 -2: tst r1,#0x40 - beq 2f - ldc p11, cr8, [ip], #64 -2: tst r1,#0x200 - beq 3f - ldcl p1, cr10, [ip], #8 - ldcl p1, cr11, [ip], #8 - ldcl p1, cr12, [ip], #8 - ldcl p1, cr13, [ip], #8 - ldcl p1, cr14, [ip], #8 - ldcl p1, cr15, [ip], #8 -3: tst lr,#1 - moveq pc,lr - bx lr - -.hidden __hwcap -1: .word __hwcap-1b diff --git a/kernel/os_setjmp.s b/kernel/os_setjmp.s deleted file mode 100644 index b74dfc68..00000000 --- a/kernel/os_setjmp.s +++ /dev/null @@ -1,39 +0,0 @@ -.global __setjmp -.global _setjmp -.global setjmp -.type __setjmp,%function -.type _setjmp,%function -.type setjmp,%function -__setjmp: -_setjmp: -setjmp: - mov ip,r0 - stmia ip!,{v1,v2,v3,v4,v5,v6,sl,fp,sp,lr} - mov r0,#0 - - adr r1,1f - ldr r2,1f - ldr r1,[r1,r2] - - tst r1,#0x260 - beq 3f - tst r1,#0x20 - beq 2f - stc p2, cr4, [ip], #48 -2: tst r1,#0x40 - beq 2f - stc p11, cr8, [ip], #64 -2: tst r1,#0x200 - beq 3f - stcl p1, cr10, [ip], #8 - stcl p1, cr11, [ip], #8 - stcl p1, cr12, [ip], #8 - stcl p1, cr13, [ip], #8 - stcl p1, cr14, [ip], #8 - stcl p1, cr15, [ip], #8 -3: tst lr,#1 - moveq pc,lr - bx lr - -.hidden __hwcap -1: .word __hwcap-1b diff --git a/kernel/pi_light.c b/kernel/pi_light.c deleted file mode 100644 index 1ffa6d9b..00000000 --- a/kernel/pi_light.c +++ /dev/null @@ -1,50 +0,0 @@ - -#include "mmap.h" -#include -#include "pi_light.h" - -//#define GPIO_BASE 0x20200000 -//#define LED_PIN 16 - -volatile unsigned int* gpio; -void set_up_LED() -{ - //Initialize the LED - gpio = (unsigned int*) GPIO_BASE; - gpio[1] |= (1 << 18); -} -void light_on() -{ - gpio[10] = (1 << LED_PIN); -} -void light_off() -{ - gpio[7] = (1 << LED_PIN); -} -void on_off() -{ - light_on(); - for (int i = 0; i < 250000; ++i) - { - } - light_off(); - for (int i = 0; i < 250000; ++i) - { - } -} -void LED_alternate() -{ - - for (int i = 0; i < 20; ++i) - { - on_off(); - } -} -void LED_alternate2(int numFlash) -{ - //Flash the ACT LED numFlash number of times - for (int i = 0; i < numFlash; ++i) - { - on_off(); - } -} diff --git a/kernel/pm.c b/kernel/pm.c deleted file mode 100644 index 14c905bc..00000000 --- a/kernel/pm.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "pm.h" -#include "stdint.h" -#include "stdarg.h" -#include "interrupt.h" -#include "klibc.h" -#include "stack.h" - -stack *stack = create_stack(); - -//method to set CPU to idle -int cpu_idle(int *fp) -{ - save_registers(); - clear_cache(); - return 0; -} - -//method to return CPU to regular operation -int cpu_resume(int *fp) -{ - enable_cache(); - return 0; -} - -//method to save registers on stack -void save_registers() -{ -push(stack, asm volatile ("r0")); -push(stack, asm volatile ("r1")); -push(stack, asm volatile ("r2")); -push(stack, asm volatile ("r3")); -push(stack, asm volatile ("r4")); -push(stack, asm volatile ("r5")); -push(stack, asm volatile ("r6")); -push(stack, asm volatile ("r7")); -push(stack, asm volatile ("r8")); -push(stack, asm volatile ("r9")); -push(stack, asm volatile ("r10")); -push(stack, asm volatile ("r11")); -push(stack, asm volatile ("r12")); - -push(stack, asm volatile ("ip")); -push(stack, asm volatile ("lr")); -push(stack, asm volatile ("pc")); -push(stack, asm volatile ("sp")); - -} - -void restore_registers() -{ - -} - -//method to clear L1 -void clear_cache() -{ -/* still need to push & pop the stack */ -/* disable cache */ -asm volatile("mov r0, #0"); -//clear r0 -asm volatile("mrc p15, 0, r0, c1, c0, 0"); -//mv control register to r0 -asm volatile("bic r0, #4"); -//!& with 4 - clears bit 2, cache bit -asm volatile("mcr p15, 0, r0, c1, c0, 0"); -//write r0 to control register - -/* clean and flush cache */ -asm volatile("mov r2, #0"); -//clear r2 -asm volatile("mcr p15, 0, r2, c7, c14, 0"); -//clean and flush data cache -asm volatile("mov r2, #0"); -//clear r2 -asm volatile("mcr p15, 0, r2, c7, c5, 0"); -//clean and flush instruction cache -} - -void enable_cache() -{ -/* enable cache */ -asm volatile("mov r0, #0"); -//clear r0 -asm volatile("mrc p15, 0, r0, c1, c0, 0"); -//mv control register to r0 -asm volatile("bic r0, #4"); -//!& with 4 - enables bit 2, cache bit -asm volatile("mcr p15, 0, r0, c1, c0, 0"); -//write r0 to control register -} diff --git a/kernel/priorityQueue.c b/kernel/priorityQueue.c deleted file mode 100644 index c37fa7f9..00000000 --- a/kernel/priorityQueue.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - Spring 2015 pcb_exec subteam: Sathya Sankaran, Jason Sim, Rakan Stanbouly - */ - -#include "priorityQueue.h" -#include "global_defs.h" -#include "vm.h" - -/* Global Variables */ -Node *head; -Node *currentNode; -/********************/ - -/* Initializes all the global variables */ -void pqueue_init() -{ - head = (Node *) mem_alloc(sizeof(Node)); - head->next = NULL; - head->prev = NULL; - head->PCB = NULL; - head->priority = NOT_SET; - head->PCB->current_state = NOT_SET; - currentNode = head; -} - -/* Add a PCB to the queue with a given priority. - Return 1 if successful. - */ -int pqueue_add(void *PCB, int priority) -{ - if (head == NULL) - { - init(); - } - - Node *newTask = (Node *) mem_alloc(sizeof(Node)); - newTask->next = NULL; - newTask->prev = NULL; - newTask->PCB = PCB; - newTask->priority = priority; - newTask->priority = PROCESS_READY; - - if (head->next == NULL) - { - head->next = (struct node *) newTask; - newTask->next = (struct node *) head; - newTask->prev = (struct node *) head; - head->prev = (struct node *) newTask; - } - else - { - // Add the new task into the correct position based on priority - currentNode = head; - while ((currentNode->next != (struct node *) head) - && (currentNode->next->priority > newTask->priority)) - { - currentNode = (Node *) currentNode->next; - } - newTask->next = currentNode->next; - newTask->prev = (struct node *) currentNode; - currentNode->next->prev = newTask; - currentNode->next = (struct node *) newTask; - } - - return 1; // Change if there should be a condition for not adding a PCB to the priority queue. -} - -/* Remove the node with the same PID as the process in the given process - control block. - - Return a pointer to the PCB removed. - */ -pcb* pqueue_remove(pcb *PCB) -{ - //PCB abstraction will change the parameters, can search for processes by PID. - currentNode = head; - while (currentNode->next->PCB->PID != PCB->PID) - { - currentNode = (Node *) currentNode->next; - } - Node *nodeToRemove = (Node *) currentNode->next; - currentNode->next = nodeToRemove->next; - currentNode->next->prev = currentNode; - nodeToRemove->next = nodeToRemove->prev = NULL; - return nodeToRemove->PCB; -} - -/* Wait for a task to finish. Then set the current task's state to READY */ -void pqueue_join(pcb *other_PCB) -{ - // TODO: Do we need to store which task(s) we are blocked on? - currentNode->PCB->current_state = PROCESS_BLOCKED; - - // Wait for the other thread to exit - while (other_PCB->current_state != PROCESS_DYING - || is_in_queue(other_PCB->PID)) - { - task_yield(); - } - currentNode->PCB->current_state = PROCESS_RUNNING; -} - -/* If the task has not been started yet, start it. - Else if the task was previously started, restore its state. - */ -void dispatch(pcb *PCB) -{ - //4-15-15: Dispatch deals with both new and old processes - if (!PCB->current_state || PCB->current_state == PROCESS_NEW) // TODO: not sure if this is correct - { - PCB->current_state = PROCESS_RUNNING; - execute_process(PCB); // Found in process.c - } - else - { - //4-15-15: This will load the VAS and jump to the location the state was saved in task_yield() - //TODO: is this all that needs to be done here to switch into the process? - vm_enable_vas(PCB->stored_vas); - load_process_state(PCB); // From process.c - ///execute_process(PCB); //This is incorrect - } -} - -/* Schedule a new task and call dispatch() to run it. */ -void schedule() -{ - // When dispatch() returns, we must schedule again, so we have use "while" - while (head->next != NULL) - { - Node *nodeToDispatch = (Node *) head->next; - - if (nodeToDispatch->PCB->current_state == PROCESS_READY) - { - nodeToDispatch->PCB->current_state = PROCESS_RUNNING; - dispatch(nodeToDispatch->PCB); - } - else - { - // If the task isn't ready, schedule another. - head = (Node *) head->next; - } - - head = head->next; - } - - // If we ever reach this part, we are out of things to schedule -} - -/* I heard we wanted voluntary yielding to start. Tasks should call this - function every so often. - */ -void task_yield() -{ - /* Save the state of the task that is currently running. We'll jump - back to here later. - */ - currentNode->PCB->current_state = PROCESS_READY; - //4-15-15: also save the VAS for the process. Hopefully this is all we need to do. - currentNode->PCB->stored_vas = vm_get_current_vas(); - int has_jumped = save_process_state(currentNode->PCB); - - if (has_jumped == FALSE) - { - // If the jump has NOT happened, schedule() - schedule(); - } - else - { - // If the jump has happened, return to the task - //4-15-15: and restore the VAS - vm_enable_vas(currentNode->PCB->stored_vas); - currentNode->PCB->current_state = PROCESS_RUNNING; - return; - } -} - -/* Return TRUE if a process with a PID of pid is in the queue. - Return FALSE otherwise. - */ -Boolean is_in_queue(int pid) -{ - Node *node_ptr = head; - - // Iterate through the list - while ((Node *) node_ptr->next != head) - { - if (node_ptr->PCB->PID == pid) - { - return TRUE; - } - - node_ptr = (Node *) node_ptr->next; - } - - return FALSE; -} diff --git a/kernel/process.c b/kernel/process.c deleted file mode 100644 index ff84825d..00000000 --- a/kernel/process.c +++ /dev/null @@ -1,283 +0,0 @@ -#include "global_defs.h" -#include "process.h" -#include "klibc.h" -#include "mem_alloc.h" -#include "loader.h" -#include "vm.h" -#include "elf.h" -#include "drivers/timer.h" -#include "fs/file.h" -#include "data_structures/bitvector.h" - -static pcb** pcb_table; -static bit_vector* pcb_map; - - -pcb* __process_create(); -void __process_elf_init(pcb* pcb_p, const char* name); -void __process_stack_init(pcb* pcb_p); -void __process_heap_init(pcb* pcb_p); - -void process_init() -{ - pcb_table = kmalloc(MAX_PROCESSES * sizeof(pcb*)); - pcb_map = make_vector(MAX_PROCESSES); -} - -pcb* process_create(const char *name) -{ - pcb* pcb_p = __process_create(); - if(!pcb_p) { - return NULL; - } - - __process_elf_init(pcb_p, name); - __process_stack_init(pcb_p); - __process_heap_init(pcb_p); - return pcb_p; -} - -int process_execute(pcb* pcb_p) -{ - //Copy the current process's program counter to the new process's return register - //The new process will use R14 to return to the parent function - asm("MOV %0, r15":"=r"(pcb_p->R14)::); - - pcb_p->current_state = PROCESS_RUNNING; - - vm_enable_vas(pcb_p->stored_vas); - process_load_state(pcb_p); - return 0; -} - -int process_destroy(pcb* pcb_p){ - bv_lower(pcb_p->PID, pcb_map); - kfree(pcb_p); - return 0; -} - -/*Spring 2015 course_os: Sathya Sankaran, Rakan Stanbouly, Jason Sim - - creates a process and initializes the PCB - @param file pointer to location in memory of file - @return pcb pointer upon success - @return 0 if there is no more room in pcb table */ -pcb* __process_create() -{ - int32_t pcb_index = bv_firstFree(pcb_map); - if (pcb_index < 0) { - return NULL; - } - pcb* pcb_p = (pcb*) kmalloc(sizeof(pcb)); - if (!pcb_p) { - return NULL; - } - //initialize PCB - pcb_p->stored_vas = vm_new_vas(); - pcb_p->PID = pcb_index; - //4-13-15: function pointer should point to main() of file pointer. - // TODO: Eventually should be able to pass parameters. Put them on the stack (argv/argc) - pcb_p->current_state = PROCESS_NEW; - pcb_p->has_executed = 0; - - pcb_table[pcb_index] = pcb_p; - bv_set(pcb_index, pcb_map); - return pcb_p; -} - -void __process_elf_init(pcb* pcb_p, const char* name) { - int fd = kopen(name, 'r'); - uint32_t start = PROC_LOCATION; - uint32_t len = 0; - - struct stats fstats; - get_stats(name, &fstats); - len = fstats.size; - os_printf("LOADING PROCESS <<%s>>, start address %X\n", - name, start, len); - - for (int i = 0; i < (len / BLOCK_SIZE) + 1; i++) - { - uint32_t *v = (uint32_t*) (start + (i * BLOCK_SIZE)); - int x = vm_allocate_page(pcb_p->stored_vas, (void*) v, VM_PERM_USER_RW); - assert(x == 0); - vm_map_shared_memory(KERNEL_VAS, (void*) v, - pcb_p->stored_vas,(void*) v, - VM_PERM_USER_RW); - } - - int* location = (int*) start; - int counter = 0; - while (counter < len) - { - kread(fd, location, 4); - location += 1; - counter += 4; - } - - Elf_Ehdr* success = (Elf_Ehdr*) load_file(pcb_p, (uint32_t*) start); - pcb_p->R15 = success->e_entry; - for (int i = 0; i < (len / BLOCK_SIZE) + 1; i++) - { - uint32_t *v = (uint32_t *) (start + (i * BLOCK_SIZE)); - vm_free_mapping(KERNEL_VAS, (void*) v); - } -} - -/* - Allocated memory for the process stack - Moves arguments for argc, argv, envp, and auxp - into stack_top - - Points stack pointer to location where stack_top would begin - @param pointer to process control block - @param pcb* pcb_p - - */ -void __process_stack_init(pcb * pcb_p) -{ - int retval = 0; - for (int i = 0; i < (STACK_SIZE / BLOCK_SIZE); i++) - { - retval = vm_allocate_page(pcb_p->stored_vas, - (void*) (STACK_BASE + (i * BLOCK_SIZE)), VM_PERM_USER_RW); - if (retval) - { - os_printf("vm_allocate_page error code: %d\n", retval); - break; - } - else - { - os_printf( - "A page have been allocated for process stack at vptr: 0x%x\n", - (STACK_BASE + (i * BLOCK_SIZE))); - } - vm_map_shared_memory(KERNEL_VAS, - (void*) (STACK_BASE + (i * BLOCK_SIZE)), pcb_p->stored_vas, - (void*) (STACK_BASE + (i * BLOCK_SIZE)), VM_PERM_USER_RW); - } - - // Stick a NULL at STACK_TOP-sizeof(int*) - uint32_t *stack_top = (uint32_t*) STACK_TOP; - stack_top[-1] = 0; - stack_top[-2] = 0; - stack_top[-3] = 0; - stack_top[-4] = 0; - stack_top[-5] = STACK_BASE; - stack_top[-6] = 1; - - os_strcpy((char*) STACK_BASE, pcb_p->name); - - // We need to set sp (r13) to stack_top - 12 - pcb_p->R13 = STACK_TOP - 4 * 6; - for (int i = 0; i < (STACK_SIZE / BLOCK_SIZE); i++) - { - vm_free_mapping(KERNEL_VAS, (void*) (STACK_BASE + (i * BLOCK_SIZE))); - } -} -void __process_heap_init(pcb* pcb_p) -{ - //from mem_alloc.c - init_process_heap(pcb_p->stored_vas); - os_printf("User Level Heap for Process PID %d initialized\n", pcb_p->PID); -} -/* - Saves all of the Registers on the machine to the PCB - @param Process ID - @return 0 if failed - @return 1 for success - */ -void process_save_state(pcb* pcb_p) -{ - assert(pcb_p); - - asm("MOV %0, r0":"=r"(pcb_p->R0)::); - asm("MOV %0, r1":"=r"(pcb_p->R1)::); - asm("MOV %0, r2":"=r"(pcb_p->R2)::); - asm("MOV %0, r3":"=r"(pcb_p->R3)::); - asm("MOV %0, r4":"=r"(pcb_p->R4)::); - asm("MOV %0, r5":"=r"(pcb_p->R5)::); - asm("MOV %0, r6":"=r"(pcb_p->R6)::); - asm("MOV %0, r7":"=r"(pcb_p->R7)::); - asm("MOV %0, r8":"=r"(pcb_p->R8)::); - asm("MOV %0, r9":"=r"(pcb_p->R9)::); - asm("MOV %0, r10":"=r"(pcb_p->R10)::); - asm("MOV %0, r11":"=r"(pcb_p->R11)::); - asm("MOV %0, r12":"=r"(pcb_p->R12)::); - asm("MOV %0, r13":"=r"(pcb_p->R13)::); - asm("MOV %0, r14":"=r"(pcb_p->R14)::); - asm("MOV %0, r15":"=r"(pcb_p->R15)::); -} - -#define offsetof(st, m) __builtin_offsetof(st, m) - -__attribute((naked)) void process_load_state(pcb* pcb_p) -{ - asm volatile( - "mov ip, r0 \n\t" \ - "ldr r0, [ip, %0] \n\t " \ - "ldr r1, [ip, %1] \n\t " \ - "ldr r2, [ip, %3] \n\t " \ - "ldr r4, [ip, %4] \n\t " \ - "ldr r5, [ip, %5] \n\t " \ - "ldr r6, [ip, %6] \n\t " \ - "ldr r7, [ip, %7] \n\t " \ - "ldr r8, [ip, %8] \n\t " \ - "ldr r9, [ip, %9] \n\t " \ - "ldr r10, [ip, %10] \n\t " \ - "ldr r11, [ip, %11] \n\t " \ - "ldr r13, [ip, %12] \n\t " \ - "ldr r14, [ip, %13] \n\t " \ - "ldr ip, [ip, %14] \n\t " \ - "mcr p15, 0, r0, c8, c7, 0 \n\t" \ - "mov r15, ip \n\t" - :: "i" (offsetof(pcb, R0)), - "i" (offsetof(pcb, R1)), - "i" (offsetof(pcb, R2)), - "i" (offsetof(pcb, R3)), - "i" (offsetof(pcb, R4)), - "i" (offsetof(pcb, R5)), - "i" (offsetof(pcb, R6)), - "i" (offsetof(pcb, R7)), - "i" (offsetof(pcb, R8)), - "i" (offsetof(pcb, R9)), - "i" (offsetof(pcb, R10)), - "i" (offsetof(pcb, R11)), - "i" (offsetof(pcb, R13)), - "i" (offsetof(pcb, R14)), - "i" (offsetof(pcb, R15)) : - ); -} -/* - Loads registers using values in pcb - @param Process ID - */ -/* -void process_load_state(pcb* pcb_p) -{ - asm("MOV r0, %0"::"r"(pcb_p->R0):); - asm("MOV r1, %0"::"r"(pcb_p->R1):); - asm("MOV r2, %0"::"r"(pcb_p->R2):); - asm("MOV r3, %0"::"r"(pcb_p->R3):); - asm("MOV r4, %0"::"r"(pcb_p->R4):); - asm("MOV r5, %0"::"r"(pcb_p->R5):); - asm("MOV r6, %0"::"r"(pcb_p->R6):); - asm("MOV r7, %0"::"r"(pcb_p->R7):); - asm("MOV r8, %0"::"r"(pcb_p->R8):); - asm("MOV r9, %0"::"r"(pcb_p->R9):); - asm("MOV r10, %0"::"r"(pcb_p->R10):); - asm("MOV r12, %0"::"r"(pcb_p->R12):); - asm("MOV r13, %0"::"r"(pcb_p->R13):); - asm("MOV r14, %0"::"r"(pcb_p->R14):); - - // move pc to process stack - *((uint32_t*)(PROC_START+4)) = pcb_p->R15; - - vm_invalidate_tlb(); - - asm("MOV r12, %0":: "i" ((PROC_START+4)):); - asm("ldr r15, [r12]" :::); - - __builtin_unreachable(); -} -*/ diff --git a/kernel/process/process_api.c b/kernel/process/process_api.c deleted file mode 100644 index e021bf31..00000000 --- a/kernel/process/process_api.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "scheduler.h" -#include "klibc.h" - -// Process / Scheduler API - -uint32_t prcs_exec(uint32_t file_p, int niceness) { - sched_task * task = sched_create_task(file_p, niceness); - return sched_add_task(task); -} - -// kill the process and its subprocesses -// can only be called if the process tree contains -// the request pid -uint32_t prcs_kill(uint32_t pid) { - return sched_remove_task(pid); -} - -// sends a message to a process (ipc) -uint32_t prcs_send_message(uint32_t dest_pid, uint32_t event, char * data, int len) { - return sched_send_message(dest_pid, event, data, len); -} - -// receives messages from processes -uint32_t prcs_register_message_callback_handler(sched_callback_handler cb_handler) { - return sched_register_callback_handler(cb_handler); -} - -// receives messages from processes -uint32_t prcs_deregister_message_callback_handler() { - return sched_deregister_callback_handler(); -} - -// set the niceness of a process -uint32_t prcs_set_niceness(uint32_t pid) { - return sched_set_niceness(pid); -} - -uint32_t prcs_fork(); // under construction diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c deleted file mode 100644 index b3cae6dc..00000000 --- a/kernel/process/scheduler.c +++ /dev/null @@ -1,513 +0,0 @@ -#include "global_defs.h" -#include "kthread.h" -#include "scheduler.h" -#include "vm.h" -#include "klibc.h" -#include "process.h" -#include "data_structures/linked_list.h" -#include "data_structures/hash_map.h" -#include "data_structures/array_list.h" -#include "drivers/timer.h" - -#define MAX_TASKS 100 // in the future, cap will be removed -#define MAX_ACTIVE_TASKS 4 // in the future, will dynamically change based on load -#define MAX_NICENESS -20 -#define MIN_NICENESS 20 -#define TASK_STATE_FINISHED 3 // task has run by the scheduler and finished -#define TASK_STATE_INACTIVE 2 // task is in the wait queue (about to be executed) -#define TASK_STATE_ACTIVE 1 // task is part of the running tasks; it is being interleaved and executed atm -#define TASK_STATE_NONE 0 // task is just created (no real state) -#define SAFE_NICE(n) MAX(MIN(MAX_NICENESS, n), n) -#define KTHREAD 0 -#define PROCESS 1 - -#define AS_PROCESS(a) ((pcb*) a->task) -#define AS_KTHREAD(a) ((kthread_handle*) a->task) -#define IS_PROCESS(a) (a->type == PROCESS) -#define IS_KTHREAD(a) (a->type == KTHREAD) - -static char *last_err; -static prq_handle * inactive_tasks; -static prq_handle * active_tasks; -static sched_task * active_task; -static hmap_handle * all_tasks_map; - -static uint32_t sched_tid; - -// NOTE -// scheduler logic only. not tested - -// scheduler -// --------- -// round-robin timer-enabled scheduler that runs tasks in descending priority -// with the help of a heap-based priority queue - -// supported syscalls -// --------- -// create: create a process (not execute) -// exec: start a process which you created before -// waitpid: wait for a process (i.e. child) to finish -// kill: kill a process and its children processes -// -#define SCHEDULER_TIMER 0 - -void __sched_dispatch(void); - -void timer_handler(void *args) -{ - os_printf("scheduler received timer interrupt, need to switch tasks...\n"); -} - -void __sched_register_timer_irq(void) -{ - register_handler(SCHEDULER_TIMER, timer_handler); -} - -void __sched_deregister_timer_irq() -{ - unregister_handler(SCHEDULER_TIMER); -} - -void __sched_pause_timer_irq() -{ - // TODO: suspend the timer here -} - -void __sched_resume_timer_irq() -{ - // TODO: resume the timer here -} - -// get the current process id -uint32_t sched_get_active_tid() { - if (active_task) { - return active_task->tid; - } - - return (uint32_t) STATUS_FAIL; -} - -// Initialize the scheduler. Should be called by the kernel ONLY -uint32_t sched_init(void) { - ensure_kernel_vas(); - - sched_tid = 0; - - os_printf("Initializing scheduler\n"); - last_err = "No error"; - inactive_tasks = prq_create_fixed(MAX_TASKS); - active_tasks = prq_create_fixed(MAX_ACTIVE_TASKS); - active_task = 0; - - all_tasks_map = hmap_create(); - - __sched_register_timer_irq(); - - return STATUS_OK; -} - -// initial call that causes the scheduler to start -void sched_start(void) -{ - __sched_dispatch(); -} - -uint32_t sched_register_callback_handler(sched_callback_handler cb_handler) { - sched_task * task = hmap_get(all_tasks_map, sched_get_active_tid()); - task->cb_handler = cb_handler; - return STATUS_OK; -} - -uint32_t sched_deregister_callback_handler() { - sched_task * task = hmap_get(all_tasks_map, sched_get_active_tid()); - task->cb_handler = 0; - - return STATUS_OK; -} - -// Free the resources used the scheduler -uint32_t sched_free() { - ensure_kernel_vas(); - - // FIXME kill active tasks - - __sched_deregister_timer_irq(); - - prq_free(inactive_tasks); - prq_free(active_tasks); - - return STATUS_OK; -} - -// issue messages for the active task -void __sched_emit_messages(void) { - if (active_task->cb_handler) { - sched_message_chunk * chunk; - while ((chunk = llist_dequeue(active_task->message_queue)) != 0) { - active_task->cb_handler(chunk->src_pid, chunk->event, chunk->data, - chunk->chunk_length, chunk->remain_length); - if (chunk) { - kfree(chunk); - } - } - } -} - -sched_task* __sched_create_task(void * task_data, int niceness, uint32_t type) { - if (prq_count(inactive_tasks) >= MAX_TASKS) { - last_err = "Too many tasks"; - return (sched_task*) STATUS_FAIL; - } - - __sched_pause_timer_irq(); - - sched_task * task = (sched_task*) kmalloc(sizeof(sched_task)); - - niceness = SAFE_NICE(niceness); - - task->tid = ++sched_tid; - task->niceness = niceness; - task->task = task_data; - task->type = type; - task->state = TASK_STATE_NONE; - task->node = 0; - task->parent_tid = 0; - task->children_tids = arrl_create(); - task->cb_handler = 0; - - if (active_task) { - task->parent_tid = active_task->tid; - arrl_append(active_task->children_tids, (void*) task->tid); - } - - __sched_resume_timer_irq(); - - return task; - -} - -sched_task* sched_create_task_from_kthread(kthread_handle * kthread, - int niceness) { - return __sched_create_task(kthread, niceness, KTHREAD); -} - -sched_task* sched_create_task_from_process(pcb * pcb_pointer, int niceness) { - return __sched_create_task(pcb_pointer, niceness, PROCESS); -} - - -// Helper function used by the scheduler internally. It will traverse the parent/child -// list to find a subtask. -#if 0 -sched_task* __sched_find_subtask(sched_task * parent_task, uint32_t tid) { - if (parent_task && parent_task->tid == tid) { - return parent_task; - } - - int i = 0; - for (; i < arrl_count(parent_task->children_tids); i++) { - uint32_t child_tid = arrl_count(parent_task, i); - sched_task * child_task = hmap_get(all_tasks_map, child_tid); - if ((child_task = __sched_find_subtask(child_task, tid))) { - return child_task; - } - } - - return 0; -} -#endif - -// -// NOTE expecting access to kernel global vars -void sched_waittid(uint32_t tid) { - // FIXME: broken! - while (1) { - sched_task * task = (sched_task*) hmap_get(all_tasks_map, (unsigned long) tid); - if (task == 0 || task->state == TASK_STATE_FINISHED) { - break; - } - - //sleep(500); - } -} - -// contract -// -------- -// must disable timer_interrupt -uint32_t __sched_remove_task(sched_task * task) { - if (task == NULL) { - return (uint32_t) STATUS_FAIL; - } - - switch (task->state) { - case TASK_STATE_INACTIVE: { - __sched_pause_timer_irq(); - prq_remove(inactive_tasks, task->node); - prq_free_node(task->node); - __sched_resume_timer_irq(); - break; - } - case TASK_STATE_ACTIVE: { - __sched_pause_timer_irq(); - - task->state = TASK_STATE_FINISHED; - - if (IS_PROCESS(task)) { - process_destroy(AS_PROCESS(task)); - } else if (IS_KTHREAD(task)) { - // FIXME add later - } - - hmap_remove(all_tasks_map, task->tid); - prq_remove(active_tasks, task->node); - prq_free_node(task->node); - - int i = 0; - for (; i < arrl_count(task->children_tids); i++) { - // FIXME: this API does not exist anymore - // sched_remove_task(arrl_get(task->children_tids, i)); - } - - __sched_resume_timer_irq(); - break; - } - case TASK_STATE_FINISHED: { - // ignore - break; - } - } - - __sched_resume_timer_irq(); - - return task->state; -} - - -// essentially a kill process -uint32_t sched_remove_task(uint32_t tid) { - sched_task * task = (sched_task*) hmap_get(all_tasks_map, tid); - if (task) { - __sched_pause_timer_irq(); - uint32_t status = __sched_remove_task(task); - __sched_resume_timer_irq(); - return status; - } - - return STATUS_FAIL; -} - -void __sched_dispatch(void) { - // prevent interrupts while handling another interrupt - __sched_pause_timer_irq(); - - // use the kernel memory - vm_use_kernel_vas(); - - if (prq_count(active_tasks) < MAX_ACTIVE_TASKS) { - if (prq_count(inactive_tasks) > 0) { - prq_enqueue(active_tasks, prq_dequeue(inactive_tasks)); // add to active_tasks if the task - } - } - - if (prq_count(active_tasks) == 0) { - __sched_resume_timer_irq(); - return; - } - - sched_task * last_task; - - // check if there is active task - if (active_task) { - last_task = active_task; - } else { - prq_node * node = prq_peek(active_tasks); - last_task = (sched_task*) node->data; - } - - switch (last_task->state) { - case TASK_STATE_INACTIVE: { - active_task = last_task; - active_task->state = TASK_STATE_ACTIVE; - - if (IS_PROCESS(active_task)) { - __sched_resume_timer_irq(); - process_execute(AS_PROCESS(active_task)); - } else if (IS_KTHREAD(active_task)) { - AS_KTHREAD(active_task)->cb_handler(); - } - - __sched_pause_timer_irq(); - sched_remove_task(active_task->tid); - active_task = 0; - - // NOTE next interrupt will get the start the process - - break; - } - case TASK_STATE_ACTIVE: { - if (prq_count(active_tasks) > 1) { - prq_remove(active_tasks, active_task->node); - prq_enqueue(active_tasks, active_task->node); - sched_task * next_task = (sched_task*) prq_peek(active_tasks)->data; - - // old task - if (IS_PROCESS(active_task)) { - if (active_task == next_task) { - vm_enable_vas(AS_PROCESS(active_task)->stored_vas); - break; - } - - process_save_state(AS_PROCESS(last_task)); - } else if (IS_KTHREAD(active_task)) { - if (active_task == next_task) { - break; - } - - // FIXME: implement - // kthread_save_state(AS_KTHREAD(active_task)); - } - - active_task = next_task; - - // new task - if (IS_PROCESS(active_task)){ - vm_enable_vas(AS_PROCESS(active_task)->stored_vas); - __sched_emit_messages(); - process_load_state(AS_PROCESS(active_task)); // continue with the next process - } else if (IS_KTHREAD(active_task)) { - __sched_emit_messages(); - - // FIXME: implement - // kthread_load_state(AS_KTHREAD(active_task)); - } - } - break; - } - } - - __sched_resume_timer_irq(); -} - -// start process -uint32_t sched_add_task(sched_task * task) { - if (task) { - if (task->state != TASK_STATE_NONE) { - last_err = "Reusing task object not allowed"; - return (uint32_t) STATUS_FAIL; - } - - ensure_kernel_vas(); - - prq_node * new_node = (prq_node*) kmalloc(sizeof(prq_node)); - new_node->data = task; - new_node->priority = task->niceness; - - task->state = TASK_STATE_INACTIVE; - task->node = new_node; - prq_enqueue(inactive_tasks, new_node); - - hmap_put(all_tasks_map, active_task->tid, active_task); - - return active_task->tid; - } - - last_err = "Invalid sched_task pointer"; - return (uint32_t) STATUS_FAIL; -} - - -const char * sched_last_err() { - return last_err; -} - -uint32_t sched_set_niceness(uint32_t pid, uint32_t niceness) { - - sched_task * task; - - if (!(task = hmap_get(all_tasks_map, pid))) { - return STATUS_FAIL; - } - - __sched_pause_timer_irq(); - - prq_handle * tasks; - - switch (task->state) { - case TASK_STATE_ACTIVE: - tasks = active_tasks; - break; - case TASK_STATE_INACTIVE: - tasks = inactive_tasks; - break; - case TASK_STATE_FINISHED: - break; - } - - if (tasks) { - prq_remove(tasks, task->node); // remove the running task from queue - task->node->priority = SAFE_NICE(niceness); - prq_enqueue(tasks, task->node); // add it again to see if its position in the queue - - } - - __sched_resume_timer_irq(); - - return STATUS_OK; -} - -uint32_t sched_post_message(uint32_t dest_pid, uint32_t event, char * data, - int len) -{ - /*sched_task * dest_task; - - if (!(dest_task = hmap_get(&all_tasks_map, dest_pid))) { - return STATUS_FAIL; - } - __sched_pause_timer_irq(); - - vm_use_kernel_vas(); - - // create space on kernel stack - char data_cpy[512]; - while (len > 0) { - // get length to cpy - int cpy_len = MIN(len, 512); - // enable orignal struct - vm_enable_vas(active_task->pcb->stored_vas); - // copy to stack - os_memcpy(data, data_cpy, cpy_len); - // remaining bytes - len -= cpy_len; - // increment data pointer - data = (char*) (data + cpy_len / 4); - // get the dest_task - sched_task * dest_task = hmap_get(&all_tasks_map, dest_pid); - // switch to dest vas - vm_enable_vas(dest_task->pcb->stored_vas); - // copy from global kernel stack to process heap - char* task_mem_data_cpy = kmalloc(cpy_len); - os_memcpy(data_cpy, task_mem_data_cpy, cpy_len); - - vm_use_kernel_vas(); - - // FIXME create the message object and pass it in - // messages will be broken up into chunks since we have to - // copy into kernel stack first. - sched_message_chunk * chunk = kmalloc(sizeof(sched_message_chunk)); - chunk->data = task_mem_data_cpy; - chunk->chunk_length = cpy_len; - chunk->remain_length = len; - chunk->event = event; - chunk->src_pid = active_task ? active_task->pcb->PID : 0; - - llist_enqueue(dest_task->message_queue, chunk); - } - - if (active_task) { - vm_enable_vas(active_task->pcb->stored_vas); - } - - __sched_resume_timer_irq();*/ - - return STATUS_OK; -} diff --git a/kernel/sampleFile.c b/kernel/sampleFile.c deleted file mode 100644 index ac8d11a1..00000000 --- a/kernel/sampleFile.c +++ /dev/null @@ -1,10 +0,0 @@ -#include - -uint32_t functionYO(uint32_t x, uint32_t y) -{ - int a = 100; - int b = 40000; - os_printf("%d\n", x + y); - return x + y; - -} diff --git a/kernel/signals.c b/kernel/signals.c deleted file mode 100644 index a299f487..00000000 --- a/kernel/signals.c +++ /dev/null @@ -1,20 +0,0 @@ -//Contributors: Andrew Stepek, Michael Brennen, and Matthew Stromberg - -/* - Signals - */ -/* - SIGKILL - SIGUSR - SIGTERM - */ - -#include "signals.h" -#include "process.h" - -void signal_mask(char * type, int index, uint32_t PID) -{ - pcb* pcb_t = get_PCB(PID); - pcb_t.mask[index]->type = type; -} - diff --git a/kernel/src/allocator/allocator.c b/kernel/src/allocator/allocator.c new file mode 100644 index 00000000..8f63c72d --- /dev/null +++ b/kernel/src/allocator/allocator.c @@ -0,0 +1,249 @@ +// Adapted from https://github.com/CCareaga/heap_allocator + + +#include +#include +#include +#include + +int offset = sizeof(uint32_t) * 2; +uint32_t overhead = sizeof(footer_t) + sizeof(node_t); + +// ======================================================== +// this function initializes a new heap structure, provided +// an empty heap struct, and a place to start the heap +// +// NOTE: this function uses HEAP_INIT_SIZE to determine +// how large the heap is so make sure the same constant +// is used when allocating memory for your heap! +// ======================================================== +void create_heap(heap_t * heap, uint32_t start) { + // first we create the initial region, this is the "wilderness" chunk + // the heap starts as just one big chunk of allocatable memory + node_t * init_region = (node_t *)start; + init_region->hole = 1; + init_region->size = (HEAP_INIT_SIZE) - sizeof(node_t) - sizeof(footer_t); + + create_foot(init_region); // create a foot (size must be defined) + + // now we add the region to the correct bin and setup the heap struct + add_node(heap->bins[get_bin_index(init_region->size)], init_region); + + heap->start = start; + heap->end = start + HEAP_INIT_SIZE; + +#ifdef MEM_DEBUG + heap->bytes_allocated = 0; +#endif +} + +// ======================================================== +// this is the allocation function of the heap, it takes +// the heap struct pointer and the size of the chunk we +// want. this function will search through the bins until +// it finds a suitable chunk. it will then split the chunk +// if neccesary and return the start of the chunk +// ======================================================== +void * heap_alloc(heap_t * heap, uint32_t size) { + // first get the bin index that this chunk size should be in + int index = get_bin_index(size); + // now use this bin to try and find a good fitting chunk! + bin_t * temp = (bin_t *)heap->bins[index]; + + node_t * found = get_best_fit(temp, size); + + // while no chunk if found advance through the bins until we + // find a chunk or get to the wilderness + while (found == NULL) { + if (index + 1 >= BIN_COUNT) return NULL; + + temp = heap->bins[++index]; + found = get_best_fit(temp, size); + } + + // if the difference between the found chunk and the requested chunk + // is bigger than the overhead (metadata size) + the min alloc size + // then we should split this chunk, otherwise just return the chunk + if ((found->size - size) > (overhead + MIN_ALLOC_SZ)) { + // do the math to get where to split at, then set its metadata + node_t * split = (node_t *)(((char *)found + overhead) + size); + split->size = found->size - size - (overhead); + split->hole = 1; + + create_foot(split); // create a footer for the split + + // now we need to get the new index for this split chunk + // place it in the correct bin + int new_idx = get_bin_index(split->size); + add_node(heap->bins[new_idx], split); + + found->size = size; // set the found chunks size + create_foot(found); // since size changed, remake foot + } + + + found->hole = 0; // not a hole anymore + remove_node(heap->bins[index], found); // remove it from its bin + + // these following lines are checks to determine if the heap should + // be expanded or contracted + // ========================================== + node_t * wild = get_wilderness(heap); + if (wild->size < MIN_WILDERNESS) { + int success = expand(heap); + if (success == 0) { return NULL; } + } else if (wild->size > MAX_WILDERNESS) { + contract(heap); + } + // ========================================== + + // since we don't need the prev and next fields when the chunk + // is in use by the user, we can clear these and return the + // address of the next field + found->prev = NULL; + found->next = NULL; + + +#ifdef MEM_DEBUG + heap->bytes_allocated += found->size; + TRACE("[MEM DEBUG] ALLOC %i bytes at 0x%x", found->size, &found->next); +#endif + + return &found->next; +} + +// ======================================================== +// this is the free function of the heap, it takes the +// heap struct pointer and the pointer provided by the +// heap_alloc function. the given chunk will be possibly +// coalesced and then placed in the correct bin +// ======================================================== +void heap_free(heap_t * heap, void * p) { + if (p == NULL) { return; } + + + bin_t * list; + footer_t *new_foot, *old_foot; + + node_t * head = (node_t *)((char *)p - offset); + +#ifdef MEM_DEBUG + heap->bytes_allocated -= head->size; + TRACE("[MEM DEBUG] FREE %i bytes", head->size); +#endif + + if (head == (node_t *)(uintptr_t)heap->start) { + head->hole = 1; + add_node(heap->bins[get_bin_index(head->size)], head); + return; + } + + node_t * next = (node_t *)((char *)get_foot(head) + sizeof(footer_t)); + footer_t * f = (footer_t *)((char *)head - sizeof(footer_t)); + node_t * prev = f->header; + + if (prev->hole) { + list = heap->bins[get_bin_index(prev->size)]; + remove_node(list, prev); + + prev->size += overhead + head->size; + new_foot = get_foot(head); + new_foot->header = prev; + + head = prev; + } + + if (next->hole) { + list = heap->bins[get_bin_index(next->size)]; + remove_node(list, next); + + head->size += overhead + next->size; + + old_foot = get_foot(next); + old_foot->header = 0; + next->size = 0; + next->hole = 0; + + new_foot = get_foot(head); + new_foot->header = head; + } + + head->hole = 1; + add_node(heap->bins[get_bin_index(head->size)], head); +} + + +// these are left here to implement contraction / expansion +uint32_t expand(heap_t * heap) { + if (vm2_allocate_page(kernell1PageTable, + heap->end, + false, + (struct PagePermission){.access = KernelRW, .executable = false}, + NULL) == NULL) { + // Pointer is NULL so error + return 0; + } else { + // Pointer is non-bn + heap->end += PAGE_SIZE; + return 1; + } +} + +void contract(heap_t * heap) { + heap->end -= PAGE_SIZE; + vm2_free_page(kernell1PageTable, heap->end); +} + +// ======================================================== +// this function is the hashing function that converts +// size => bin index. changing this function will change +// the binning policy of the heap. right now it just +// places any allocation < 8 in bin 0 and then for anything +// above 8 it bins using the log base 2 of the size +// ======================================================== +uint32_t get_bin_index(uint32_t sz) { + int index = 0; + sz = sz < 4 ? 4 : sz; + + while (sz >>= 1) index++; + index -= 2; + + if (index > BIN_MAX_IDX) index = BIN_MAX_IDX; + + return index; +} + +// ======================================================== +// this function will create a footer given a node +// the node's size must be set to the correct value! +// ======================================================== +void create_foot(node_t * head) { + footer_t * foot = get_foot(head); + foot->header = head; +} + + +// ======================================================== +// this function will get the footer pointer given a node +// ======================================================== +footer_t * get_foot(node_t * node) { + return (footer_t *)((char *)node + sizeof(node_t) + node->size); +} + +// ======================================================== +// this function will get the wilderness node given a +// heap struct pointer +// +// NOTE: this function banks on the heap's end field being +// correct, it simply uses the footer at the end of the +// heap because that is always the wilderness +// ======================================================== +node_t * get_wilderness(heap_t * heap) { + footer_t * wild_foot = (footer_t *)((char *)heap->end - sizeof(footer_t)); + return wild_foot->header; +} + +uint32_t get_alloc_size(void * ptr) { + node_t * head = (node_t *)(ptr - offset); + return head->size; +} diff --git a/kernel/src/allocator/include/allocator.h b/kernel/src/allocator/include/allocator.h new file mode 100644 index 00000000..93b4f292 --- /dev/null +++ b/kernel/src/allocator/include/allocator.h @@ -0,0 +1,76 @@ +// Adapted from https://github.com/CCareaga/heap_allocator + +#ifndef ALLOCATOR_H +#define ALLOCATOR_H + +#include + +#define HEAP_INIT_SIZE 0x10000 +#define HEAP_MAX_SIZE 0xF0000 +#define HEAP_MIN_SIZE 0x10000 + +#define MIN_ALLOC_SZ 4 + +#define MIN_WILDERNESS 0x2000 +#define MAX_WILDERNESS 0x1000000 + +#define BIN_COUNT 9 +#define BIN_MAX_IDX (BIN_COUNT - 1) + +/// Heap + +typedef struct node_t { + uint32_t hole; + uint32_t size; + struct node_t * next; + struct node_t * prev; +} node_t; + +typedef struct { + node_t * header; +} footer_t; + +typedef struct { + node_t * head; +} bin_t; + +typedef struct { + uint32_t start; + uint32_t end; + bin_t * bins[BIN_COUNT]; + +#ifdef MEM_DEBUG + size_t bytes_allocated; +#endif +} heap_t; + +uint32_t overhead; + +void create_heap(heap_t * heap, uint32_t start); + +void * heap_alloc(heap_t * heap, uint32_t size); +void heap_free(heap_t * heap, void * p); +uint32_t expand(heap_t * heap); +void contract(heap_t * heap); + +uint32_t get_bin_index(uint32_t sz); +void create_foot(node_t * head); +footer_t * get_foot(node_t * head); + +node_t * get_wilderness(heap_t * heap); + +uint32_t get_alloc_size(void * ptr); + +/// Linked list + +void add_node(bin_t * bin, node_t * node); + +void remove_node(bin_t * bin, node_t * node); + +node_t * get_best_fit(bin_t * list, uint32_t size); +node_t * get_last_node(bin_t * list); + +node_t * next(node_t * current); +node_t * prev(node_t * current); + +#endif diff --git a/kernel/src/allocator/include/mem_alloc.h b/kernel/src/allocator/include/mem_alloc.h new file mode 100644 index 00000000..f70b09a1 --- /dev/null +++ b/kernel/src/allocator/include/mem_alloc.h @@ -0,0 +1,21 @@ +#ifndef MEM_ALLOC_H +#define MEM_ALLOC_H + +#include +#include + + +void init_heap(); +void * allocate(uint32_t size); +void deallocate(void * ptr); + +heap_t * mem_get_allocator(); +uint32_t mem_get_heap_size(); + +// get size of allocated blocks +uint32_t allocation_size(void * ptr); +uint32_t proc_blocksize(void * ptr); + +size_t heap_end; + +#endif diff --git a/kernel/src/allocator/llist.c b/kernel/src/allocator/llist.c new file mode 100644 index 00000000..4ae3e5ad --- /dev/null +++ b/kernel/src/allocator/llist.c @@ -0,0 +1,85 @@ +#include +#include + +void add_node(bin_t * bin, node_t * node) { + node->next = NULL; + node->prev = NULL; + + if (bin->head == NULL) { + bin->head = node; + return; + } + + // we need to save next and prev while we iterate + node_t * current = bin->head; + node_t * previous = NULL; + // iterate until we get the the end of the list or we find a + // node whose size is + while (current != NULL && current->size <= node->size) { + previous = current; + current = current->next; + } + + if (current == NULL) { // we reached the end of the list + if (previous == NULL) { FATAL("BUG: previous shouldn't be null, this is probably a bug!"); } + + previous->next = node; + node->prev = previous; + } else { + if (previous != NULL) { // middle of list, connect all links! + node->next = current; + previous->next = node; + + node->prev = previous; + current->prev = node; + } else { // head is the only element + node->next = bin->head; + bin->head->prev = node; + bin->head = node; + } + } +} + +void remove_node(bin_t * bin, node_t * node) { + if (bin->head == NULL) return; + if (bin->head == node) { + bin->head = bin->head->next; + return; + } + + node_t * temp = bin->head->next; + while (temp != NULL) { + if (temp == node) { // found the node + if (temp->next == NULL) { // last item + temp->prev->next = NULL; + } else { // middle item + temp->prev->next = temp->next; + temp->next->prev = temp->prev; + } + // we dont worry about deleting the head here because we already checked that + return; + } + temp = temp->next; + } +} + +node_t * get_best_fit(bin_t * bin, uint32_t size) { + if (bin->head == NULL) return NULL; // empty list! + + node_t * temp = bin->head; + + while (temp != NULL) { + if (temp->size >= size) { + return temp; // found a fit! + } + temp = temp->next; + } + return NULL; // no fit! +} + +node_t * get_last_node(bin_t * bin) { + node_t * temp = bin->head; + + while (temp->next != NULL) { temp = temp->next; } + return temp; +} diff --git a/kernel/src/allocator/mem_alloc.c b/kernel/src/allocator/mem_alloc.c new file mode 100644 index 00000000..9fc7558a --- /dev/null +++ b/kernel/src/allocator/mem_alloc.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include + +heap_t * allocator; +size_t heap_end; + +/// Initializes the heap by asking for HEAP_INIT_SIZE of pages, and putting the heap datastructure +/// there. After the heap is initialized [kmalloc] and related functions can be used. +void init_heap() { + heap_end = KERNEL_HEAP_BASE; + + // Allocate space for the heap_t struct. is too large but at least big enough. + void * ret = vm2_allocate_page(kernell1PageTable, + KERNEL_HEAP_BASE, + false, + (struct PagePermission){.access = KernelRW, .executable = false}, + NULL); + if (ret == NULL) { FATAL("Couldn't allocate page for the kernel heap"); } + + heap_t * heap = (heap_t *)KERNEL_HEAP_BASE; + + memset(heap, 0, sizeof(heap_t)); + + heap_end += sizeof(heap_t); + + + for (int i = 0; i < BIN_COUNT; i++) { + heap->bins[i] = (bin_t *)heap_end; + memset(heap->bins[0], 0, sizeof(bin_t)); + heap_end += sizeof(bin_t); + } + + assert(KERNEL_HEAP_BASE + sizeof(heap_t) + BIN_COUNT * sizeof(bin_t) == heap_end); + + // current heap end. + heap_end = ALIGN(heap_end, PAGE_SIZE); + size_t heap_start = heap_end; + + while (heap_end < (heap_start + HEAP_INIT_SIZE)) { + if (vm2_allocate_page(kernell1PageTable, + heap_end, + false, + (struct PagePermission){.access = KernelRW, .executable = false}, + NULL) == NULL) { + FATAL("Allocation of the kernel heap went wrong!"); + } + + heap_end += PAGE_SIZE; + } + + assert(heap_end >= (heap_start + HEAP_INIT_SIZE)); + + create_heap(heap, heap_start); + allocator = heap; + + INFO("Heap successfully initialized."); +} + +/// Internal wrapper around heap_alloc. Should only be indirectly used through +/// kmalloc/krealloc/kcalloc/kfree +void * allocate(uint32_t size) { + return heap_alloc(allocator, size); +} + +/// Internal wrapper around heap_free. Should only be indirectly used through +/// kmalloc/krealloc/kcalloc/kfree +void deallocate(void * ptr) { + return heap_free(allocator, ptr); +} + +/// Internal function to get the size of an allocation. Should only be indirectly used through +/// kmalloc/krealloc/kcalloc/kfree +uint32_t allocation_size(void * ptr) { + return get_alloc_size(ptr); +} + +/// Internal function to get the global allocator. Should only be indirectly used through +/// kmalloc/krealloc/kcalloc/kfree +heap_t * mem_get_allocator() { + return allocator; +} + +/// Internal function to get the size of the heap. Should only be indirectly used through +/// kmalloc/krealloc/kcalloc/kfree +uint32_t mem_get_heap_size() { + return allocator->end - allocator->start; +} diff --git a/kernel/src/allocator/test/test_allocator.c b/kernel/src/allocator/test/test_allocator.c new file mode 100644 index 00000000..2058523c --- /dev/null +++ b/kernel/src/allocator/test/test_allocator.c @@ -0,0 +1,52 @@ +#include +#include + +TEST_CREATE(test_alloc_free, { + uint32_t * a = kmalloc(sizeof(uint32_t)); + *a = 42; + kfree(a); +}) + +TEST_CREATE(test_alloc_free_large, { + uint32_t * a = kmalloc(100 * sizeof(uint32_t)); + for (int i = 0; i < 100; i++) { a[i] = 42; } + kfree(a); +}) + +TEST_CREATE(test_alloc_realloc_free, { + uint32_t * a = kmalloc(5 * sizeof(uint32_t)); + for (int i = 0; i < 5; i++) { a[i] = 42; } + + a = krealloc(a, 100 * sizeof(uint32_t)); + for (int i = 5; i < 100; i++) { a[i] = 42; } + + kfree(a); +}) + +TEST_CREATE(test_free_null, { kfree(NULL); }) + +TEST_CREATE(test_calloc, { + int * test = kcalloc(100, sizeof(int)); + + for (int i = 0; i < 100; i++) { ASSERT_EQ(test[i], 0); } + + kfree(test); +}) + +TEST_CREATE(test_expand_heap, { + uint32_t initial_end = heap->end; + + expand(heap); + + ASSERT_EQ(heap->end, initial_end + 0x1000); + + uint8_t * yolo = (void *)(heap->end - 300); + uint8_t prev = *yolo; + *yolo = 42; + ASSERT_EQ(*yolo, 42); + *yolo = prev; + + contract(heap); + + ASSERT_EQ(heap->end, initial_end); +}) diff --git a/kernel/src/common/hardwareinfo.c b/kernel/src/common/hardwareinfo.c new file mode 100644 index 00000000..18d91dc8 --- /dev/null +++ b/kernel/src/common/hardwareinfo.c @@ -0,0 +1,63 @@ +#include +#include +#include + +static HardwareInfo hardware_info; + +BoardType detect_boardtype() { + uint32_t reg; + + // read system register + asm("mrc p15,0,%0,c0,c0,0" : "=r"(reg)); + + uint32_t type = (reg >> 4u) & 0xFFFu; + + switch (type) { + case 0xB76: + return RaspberryPiZero; // bcm2835 + case 0xC07: + return RaspBerryPiTwo; // bcm2836 + default: + FATAL("Unknown boardtype"); + } +} + +// TODO: detect hardware info. +// Such as: CPU and RAM. +void init_hardwareinfo() { + hardware_info = (HardwareInfo){ + .cpuType = ARM1176, + .boardType = detect_boardtype(), + }; +} + +HardwareInfo * get_hardwareinfo() { + return &hardware_info; +} + +void print_hardwareinfo() { + kprintf("==============================================\n"); + kprintf("Hardware info detected:\n"); + switch (hardware_info.cpuType) { + case ARM1176: + kprintf("CPU type: %s\n", "ARM 1176"); + break; + case CortexA7: + kprintf("CPU type: %s\n", "Cortex A7"); + break; + } + + switch (hardware_info.boardType) { + case RaspberryPiZero: + kprintf("Board type: %s\n", "Raspberry Pi zero or 1b+"); + break; + case RaspBerryPiTwo: + kprintf("Board type: %s\n", "Raspberry Pi two"); + break; + case VersatilePB: + kprintf("Board type: %s\n", "Versatile PB"); + break; + } + + kprintf("==============================================\n"); +} diff --git a/kernel/src/common/include/hardwareinfo.h b/kernel/src/common/include/hardwareinfo.h new file mode 100644 index 00000000..4c875bf4 --- /dev/null +++ b/kernel/src/common/include/hardwareinfo.h @@ -0,0 +1,22 @@ +#ifndef HARDWAREINFO_H +#define HARDWAREINFO_H + +typedef enum CpuType { ARM1176, CortexA7 } CpuType; + +typedef enum BoardType { VersatilePB, RaspberryPiZero, RaspBerryPiTwo } BoardType; + + +// TODO: memory size? +typedef struct HardwareInfo { + CpuType cpuType; + BoardType boardType; +} HardwareInfo; + +void init_hardwareinfo(); + +// Get a pointer to the hardwareinfo struct. +HardwareInfo * get_hardwareinfo(); +void print_hardwareinfo(); +BoardType detect_boardtype(); + +#endif diff --git a/kernel/src/common/include/interrupt.h b/kernel/src/common/include/interrupt.h new file mode 100644 index 00000000..f05c3b48 --- /dev/null +++ b/kernel/src/common/include/interrupt.h @@ -0,0 +1,86 @@ +#ifndef __HW_HANDLERS_H__ +#define __HW_HANDLERS_H__ + +/* + * + * Hardware Handler Interface for course_os + * + * + * A bit of background: + * - The ARM architecture has 7 modes of operation: + * + USR - User mode + * + FIQ - processing "fast" interrupts + * + IRQ - processing "normal" interrupts + * + SVC - Supervisor/Kernel mode + * + UND - processing an undefined instruction exception + * + SYS - Privileged mode but retains the registers of the user mode, used for handling interrupts + * in a faster way. These modes can be entered or exited by modifying the CPSR (status register) + * + * All modes have their own stack which can be found in [stacks.s](stacks.s] + * + * Exceptions (e.g. software interrupts, system calls, etc.), Interrupts (IRQ, FIQ) + * trigger the core to switch to an appropriate mode and the pc to jump to a + * preset address (somewhere in the vector table) for a branch instruction to the + * proper handler. + * + * When this happens the state of the machine must be preserved. The HW handler interface + * centralizes the 'top half' exception/interrupt handling code and takes care of the dirty + * low-level work so that the software handling interfaces for interrupts, system calls, and + * exceptions can be written more clearly elsewhere. + * + * tl;dr - write your handlers as a separate module and call them from one + * of the prototypes below. + * + */ +#include "stdint.h" + +#define BRANCH_INSTRUCTION 0xe59ff018 // ldr pc, pc+offset (where offset is 0x20 bytes) + +void init_vector_table(void); + +// vector table handlers, should be loaded at 0x00 in this order! +extern void _Reset(); + +void reset_handler(void); + +void __attribute__((interrupt("UNDEF"))) undef_instruction_handler(); // 0x04 +void swi_handler(void * registers); // Initially handled in asm +void __attribute__((interrupt("ABORT"))) prefetch_abort_handler(); // 0x0c +void __attribute__((interrupt("ABORT"))) data_abort_handler(); // 0x10 +void reserved_handler(); // 0x14 +void __attribute__((interrupt("IRQ"))) irq_handler(); // 0x18 +void __attribute__((interrupt("FIQ"))) fiq_handler(); // 0x1c + +/** + * Semihosting calls + * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471g/CHDJHHDI.html + */ +enum SemihostingSWI { + BreakPoint = 0x20020, + WatchPoint = 0x20021, + StepComplete = 0x20022, + RunTimeErrorUnknown = 0x20023, // Qemu exits with 1 + InternalError = 0x20024, // Qemu exits with 1 + UserInterruption = 0x20025, // Qemu exits with 1 + ApplicationExit = 0x20026, // Qemu exits with 0 + StackOverflow = 0x20027, // Qemu exits with 1 + DivisionByZero = 0x20028, // Qemu exits with 1 + OSSpecific = 0x20029, // Qemu exits with 1 +}; + +void SemihostingCall(enum SemihostingSWI mode); + +void SemihostingOSExit(uint8_t code) __attribute__((noreturn)); + +typedef enum { + IRQ, // (this is bit 0x8 on the CPSR) + FIQ, // (this is bit 0x4 on the CPSR) + BOTH +} InterruptType; + +void enable_interrupt(InterruptType); +int enable_interrupt_save(InterruptType); +void disable_interrupt(InterruptType); +int disable_interrupt_save(InterruptType); + +#endif diff --git a/kernel/src/common/include/interrupt_asm.h b/kernel/src/common/include/interrupt_asm.h new file mode 100644 index 00000000..9b2ac770 --- /dev/null +++ b/kernel/src/common/include/interrupt_asm.h @@ -0,0 +1,8 @@ +#ifndef COURSE_OS_INTERRUPT_ASM_H +#define COURSE_OS_INTERRUPT_ASM_H + +#include "interrupt.h" + +long __attribute__((interrupt("SWI"))) software_interrupt_handler(); // 0x08 + +#endif // COURSE_OS_INTERRUPT_ASM_H diff --git a/kernel/src/common/include/kernel_programs.h b/kernel/src/common/include/kernel_programs.h new file mode 100644 index 00000000..36ffff52 --- /dev/null +++ b/kernel/src/common/include/kernel_programs.h @@ -0,0 +1,2 @@ +void kernel_one(); +void kernel_two(); diff --git a/kernel/src/common/interrupt.c b/kernel/src/common/interrupt.c new file mode 100644 index 00000000..08e0057b --- /dev/null +++ b/kernel/src/common/interrupt.c @@ -0,0 +1,277 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* copy vector table from wherever QEMU loads the kernel to 0x00 */ +void init_vector_table() { + // allocate space for the IVR at the high vector location. + vm2_allocate_page(kernell1PageTable, + HIGH_VECTOR_LOCATION, + false, + (struct PagePermission){.access = KernelRW, .executable = true}, + NULL); + + /* Primary Vector Table */ + mmio_write(HIGH_VECTOR_LOCATION + 0x00, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x04, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x08, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x0C, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x10, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x14, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x18, BRANCH_INSTRUCTION); + mmio_write(HIGH_VECTOR_LOCATION + 0x1C, BRANCH_INSTRUCTION); + + /* Secondary Vector Table */ + mmio_write(HIGH_VECTOR_LOCATION + 0x20, &reset_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x24, &undef_instruction_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x28, &software_interrupt_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x2C, &prefetch_abort_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x30, &data_abort_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x34, &reserved_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x38, &irq_handler); + mmio_write(HIGH_VECTOR_LOCATION + 0x3C, &fiq_handler); + + /// Enable high vectors (Vectors located at HIGH_VECTOR_LOCATION). + asm volatile("mrc p15, 0, r1, c1, c0, 0 \n" // Read p15 + "orr r1, %0\n" // Enable High Vector bit + "mcr p15, 0, r1, c1, c0, 0\n" // Set p15 + ::"r"(1u << 13u)); +} + +/* handlers */ +void reset_handler(void) { + INFO("RESET HANDLER\n"); + _Reset(); +} + +void __attribute__((interrupt("UNDEF"))) undef_instruction_handler() { + size_t spsr, lr; + + asm volatile("mrs %0, spsr" : "=r"(spsr)); + asm volatile("mov %0, lr" : "=r"(lr)); + + size_t thumb = spsr & 0x20u; + size_t pc = thumb ? lr - 0x2u : lr - 0x4u; + + + WARN("UNDEFINED INSTRUCTION HANDLER"); + + size_t copro = (*(size_t *)pc & 0xf00000u) >> 24u; + + if (spsr & 0x20u) { + WARN("THUMB mode"); + } else { + WARN("ARM mode"); + } + if (spsr & 0x1000000u) { WARN("JAZELLE enabled"); } + + WARN("COPRO: 0x%x", copro); + WARN("violating instruction (at 0x%x): 0x%x", pc, *((size_t *)pc)); + if (pc >= KERNEL_VIRTUAL_START && pc < KERNEL_VIRTUAL_END) { + WARN("(instruction is in kernel address range)"); + } + + FATAL("UNDEFINED INSTRUCTION HANDLER"); +} + +void swi_handler(void * registers) { + Scheduler * scheduler = get_scheduler(); + Thread * thread = get_thread(scheduler); + set_registers(thread, registers); + + handle_syscall(thread->registers.R7, + thread->registers.R0, + thread->registers.R1, + thread->registers.R2, + thread->registers.R3); + + schedule_task(scheduler); +} + +void __attribute__((interrupt("ABORT"))) prefetch_abort_handler(void) { + size_t lr; + asm volatile("mov %0, lr" : "=r"(lr)); + + FATAL("PREFETCH ABORT HANDLER, violating address: 0x%x", (lr - 4u)); +} + +void __attribute__((interrupt("ABORT"))) data_abort_handler(void) { + // TODO Check if the address is valid according to the kernel and add it to the currently loaded + // pagetables if so. + + int lr; + asm volatile("mov %0, lr" : "=r"(lr)); + int pc = lr - 8; + + uint32_t far; + asm volatile("mrc p15, 0, %0, c6, c0, 0" : "=r"(far)); + + WARN("DATA ABORT HANDLER (Page Fault)"); + WARN("faulting address: 0x%x", far); + if (far >= KERNEL_VIRTUAL_OFFSET) { DEBUG("(address is in kernel address range)"); } + WARN("violating instruction (at 0x%x): 0x%x", pc, *((int *)pc)); + + // Get the Data Fault Status Register + int dfsr; + asm volatile("MRC p15, 0, %0, c5, c0, 0" : "=r"(dfsr)); + WARN("DFSR: 0x%x", dfsr); + + +#ifdef ENABLE_TESTS + FATAL("Data abort is disallowed in tests"); +#endif +} + +void reserved_handler(void) { + INFO("RESERVED HANDLER\n"); +} + +// the attribute automatically saves and restores state +// TODO: We might not want that! (context switches etc) +void __attribute__((interrupt("IRQ"))) irq_handler(void) { + DEBUG("IRQ HANDLER"); + return chipset.handle_irq(); + + // int * pendingregister = (int *) 0x40000060; + // int cpsr = disable_interrupt_save(IRQ); + + // os_printf("disabled CSPR:%X\n",cpsr); + // Discover source of interrupt + // do a straight run through the VIC_INT_STATUS to determine + // which interrupt lines need to be tended to + // for (int i = 0; i < MAX_NUM_INTERRUPTS; i++) { + // // is the line active? + // if ((1 << i) & mmio_read(&interrupt_registers->irq_basic_pending)) { + // // activate that specific handler + // handle_irq_interrupt(i); + // } + // } + // we've gone through the VIC and handled all active interrupts + // restore_proc_status(cpsr); + + // enable_interrupt(IRQ_MASK); +} + +void __attribute__((interrupt("FIQ"))) fiq_handler(void) { + DEBUG("FIQ HANDLER\n"); + return chipset.handle_fiq(); + + // handle_irq_interrupt(interrupt_registers->fiq_control & 0x7f); + + + // FIQ handler returns from the interrupt by executing: + // SUBS PC, R14_fiq, #4 +} + +void __attribute__((always_inline)) inline SemihostingCall(enum SemihostingSWI mode) { + int a = mode; + asm volatile("MOV r0, #0x18\n" + "LDR r1, %[in0]\n" + "svc 0x00123456\n" + : + : [in0] "m"(a)); +} + + +/// Uses the ExtendedExit Semihosting call +/// ARM Docs: +/// https://developer.arm.com/docs/100863/0200/semihosting-operations/sys_exit_extended-0x20 +void __attribute__((always_inline)) inline SemihostingOSExit(uint8_t code) { + struct { + uint32_t f1; + uint32_t f2; + } parameters = {ApplicationExit, code}; + + asm volatile("MOV r0, #0x20\n" + "mov r1, %[in0]\n" + "svc 0x00123456\n" ::[in0] "r"(¶meters)); + + __builtin_unreachable(); +} + +/* enable IRQ and/or FIQ */ +void enable_interrupt(InterruptType mask) { + INFO("Enabling interrupts with mask 0x%x", mask); + + // enable interrupt on the core + switch (mask) { + case IRQ: + asm volatile("cpsie i"); + break; + case FIQ: + asm volatile("cpsie f"); + break; + case BOTH: + asm volatile("cpsie if"); + break; + default: + /** should never happen **/ + WARN("invalid interrupt mask"); + } +} + +/* disable IRQ and/or FIQ */ +void disable_interrupt(InterruptType mask) { + INFO("Disabling interrupts with mask 0x%x", mask); + + // disable interrupts on the core + switch (mask) { + case IRQ: + asm volatile("cpsid i"); + break; + case FIQ: + asm volatile("cpsid f"); + break; + case BOTH: + asm volatile("cpsid if"); + break; + default: + /** should never happen **/ + WARN("invalid interrupt mask"); + } +} + +/* disable IRQ and/or FIQ, but also return a copy of the CPSR */ +int disable_interrupt_save(InterruptType mask) { + INFO("Disabling interrupts (save) with mask 0x%x", mask); + + /* get a copy of the current process status register */ + int cpsr; + asm volatile("mrs %0, cpsr" : "=r"(cpsr)); + // disable interrupts on the core + switch (mask) { + case IRQ: + asm volatile("cpsid i"); + break; + case FIQ: + asm volatile("cpsid f"); + break; + case BOTH: + asm volatile("cpsid if"); + break; + default: + /** should never happen **/ + WARN("invalid interrupt mask"); + } + return cpsr; +} + +/* return a full 32-bit copy of the current process status register */ +size_t get_proc_status() { + size_t cpsr; + asm volatile("mrs %0, cpsr" : "=r"(cpsr)); + return cpsr; +} + +/* restore control status (interrupt, mode bits) of the cpsr */ +/* (e.g. when we return from a handler, restore value from + disable_interrupt_save */ +void restore_proc_status(size_t cpsr) { + asm volatile("msr cpsr_c, %0" : : "r"(cpsr)); +} diff --git a/kernel/src/common/interrupt_asm.s b/kernel/src/common/interrupt_asm.s new file mode 100644 index 00000000..c675fd11 --- /dev/null +++ b/kernel/src/common/interrupt_asm.s @@ -0,0 +1,25 @@ +.text + .global software_interrupt_handler + +software_interrupt_handler: + // Push all registers to the stack + push {r0} // Should be replaced with cpsr + mov r0, sp + sub r0, #4 + push {lr} // PC + push {lr} + push {r0} // SP + stmdb sp!,{r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12}^ + + add sp, #64 + ldr r1, [sp, #0] // restore r0 + mrs r0, spsr + push {r0} // CPSR + sub sp, #60 + + push {r1} // push r0 + + // Call the C swi handler + mov r0, sp + mov lr, #42 // Marker, in case it ever shows up as pc address. + bl swi_handler diff --git a/kernel/src/common/kernel_programs.c b/kernel/src/common/kernel_programs.c new file mode 100644 index 00000000..1f6ab7a6 --- /dev/null +++ b/kernel/src/common/kernel_programs.c @@ -0,0 +1,29 @@ +#include + +void kernel_one() { + /** asm volatile( + "mov %r7, $4 \n" \ + "swi $0 \n" + ); */ + kprintf("Starting kernel program one.\n"); + + for (size_t i = 0; i < 100; i++) { + kprintf("Hello #%i from program one.\n", i); + } + + kprintf("Goodbye from program one.\n"); +} + +void kernel_two() { + asm volatile( + "mov %r7, $4 \n" \ + "swi $0 \n" + ); + kprintf("Starting kernel program two.\n"); + + for (size_t i = 0; i < 100; i++) { + kprintf("Hello #%i from program two.\n", i); + } + + kprintf("Goodbye from program two.\n"); +} diff --git a/kernel/src/common/stacks.s b/kernel/src/common/stacks.s new file mode 100644 index 00000000..82175576 --- /dev/null +++ b/kernel/src/common/stacks.s @@ -0,0 +1,79 @@ +// This code creates multiple areas that are used as stacks for each of the +// CPU operating modes. + +// Codes for the various execution modes +// https://heyrick.eu/armwiki/Processor_modes +.equ Mode_USR, 0x10 // User +.equ Mode_FIQ, 0x11 // Fast interrupt +.equ Mode_IRQ, 0x12 // Normal iterrupt +.equ Mode_SVC, 0x13 // Supervisor mode, this is the privileged moded for the OS (/Kernel) +.equ Mode_MON, 0x16 // Monitor, more info: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.prd29-genc-009492c/CACJBHJA.html +.equ Mode_ABT, 0x17 // Abort, for virtual memory and memory protection +.equ Mode_UND, 0x1B // Undefined, +.equ Mode_SYS, 0x1F // System, a hybrid between SVC and + +.text + +.global stacks +stacks: + // FIQ Stack + MSR CPSR_c, #Mode_FIQ // Switch to FIQ Mode + LDR sp, =FIQ_STACK_TOP // Set the FIQ stack pointer + + // IRQ Stack + MSR CPSR_c, #Mode_IRQ + LDR sp, =IRQ_STACK_TOP + + // MON Stack + MSR CPSR_c, #Mode_MON + LDR sp, =MON_STACK_TOP + + // ABT Stack + MSR CPSR_c, #Mode_ABT + LDR sp, =ABT_STACK_TOP + + // UND Stack + MSR CPSR_c, #Mode_UND + LDR sp, =UND_STACK_TOP + + // SYS Stack + MSR CPSR_c, #Mode_SYS + LDR sp, =SYS_STACK_TOP + + // Switch back SVC/Kernel + MSR CPSR_c, #Mode_SVC + ADD fp, sp, #0 // ??? + + bx lr + +.section .bss +.global KERNEL_STACK_TOP +KERNEL_STACK_START: + .space 0x10000 // 16 KiB of stack should be enough +KERNEL_STACK_TOP: + +FIQ_STACK_START: + .space 1024 // 1 KiB of stack for the FIQ handlers +FIQ_STACK_TOP: + +IRQ_STACK_START: + .space 1024 // 1 KiB of stack for the FIQ handlers +IRQ_STACK_TOP: + +ABT_STACK_START: + .space 1024 // 1 KiB of stack for abort modes +ABT_STACK_TOP: + +// TODO: We are not quite sure what this processor mode is and why it needs a stack, +// TODO: but the previous people gave it as stack as well so it seems useful... +MON_STACK_START: + .space 1024 // 1 KiB of stack for monitor modes +MON_STACK_TOP: + +UND_STACK_START: + .space 1024 // 1 KiB of stack for undefined modes +UND_STACK_TOP: + +SYS_STACK_START: + .space 1024 // 1 KiB of stack for undefined modes +SYS_STACK_TOP: diff --git a/kernel/src/common/start.c b/kernel/src/common/start.c new file mode 100644 index 00000000..047f06fd --- /dev/null +++ b/kernel/src/common/start.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/// Entrypoint for the C part of the kernel. +/// This function is called by the assembly located in [startup.s]. +/// The MMU has already been initialized here but only the first MiB of the kernel has been mapped. +void start(uint32_t * p_bootargs) { + // Before this point, all code has to be hardware independent. + // After this point, code can request the hardware info struct to find out what + // Code should be ran. + init_hardwareinfo(); + + // Initialize the chipset and enable uart + init_chipset(); + + INFO("Started chipset specific handlers"); + + // just cosmetic (and for debugging) + print_hardwareinfo(); + detect_boardtype(); + + // start proper virtual and physical memory management. + // Even though we already enabled the mmu in startup.s to + // create a higher half kernel. The pagetable created there + // was temporary and has to be replaced here. + // This will actually map the whole kernel in memory and initialize the physicalMemoryManager. + INFO("Initializing the physical and virtual memory managers."); + vm2_start(); + + INFO("Setting up interrupt vector tables"); + // Set up the exception handlers. + init_vector_table(); + + INFO("Setting up heap"); + // After this point kmalloc and kfree can be used for dynamic memory management. + init_heap(); + + // Splash screen + splash(); + + // Turn on interrupts + enable_interrupt(BOTH); + + // Call the chipset again to do any initialization after enabling interrupts and the heap. + chipset.late_init(); + + Scheduler *scheduler = create_scheduler(); + +#ifndef ENABLE_TESTS +// argparse_process(p_bootargs); +// +// TODO: Start init process +#else + test_main(); + // If we return, the tests failed. + SemihostingCall(OSSpecific); +#endif + + Elf *elf = elf_decode(swi, swi_len); + + // Process *process1 = create_process(kernel_one, NULL); + Process *process2 = create_process(elf, NULL); + // add_process_to_scheduler(scheduler, process1); + add_process_to_scheduler(scheduler, process2); + + enable_scheduler(scheduler); + free_scheduler(scheduler); + + // TODO: + // * Mount vfs + // * Load initramfs into tmpfs + // * execute userland init program + + asm volatile("cpsie i"); + + INFO("End of boot sequence.\n"); + SLEEP; +} diff --git a/kernel/src/common/startup.s b/kernel/src/common/startup.s new file mode 100644 index 00000000..9ef54384 --- /dev/null +++ b/kernel/src/common/startup.s @@ -0,0 +1,80 @@ + +.global _Reset + +// Actual entrypoint of the Kernel. +_Reset: + // Disable other cores + mrc p15, #0, r1, c0, c0, #5 + and r1, r1, #3 + cmp r1, #0 + bne loop + + ldr sp, =EARLY_KERNEL_STACK_TOP // Set the kernel/SVC stack + push {r0-r11} + + // Identity map 0x00000000 (the kernel) + ldr r0, =0x4000 + mov r1, #0 + orr r1, #0x02 + orr r1, #0x400 + str r1, [r0] + + // Map the lowest 1Mb to 0x8000000 + ldr r0, =__KERNEL_BASE + lsr r0, #20 + lsl r0, #2 + ldr r1, =0x4000 + add r0, r1, r0 + + mov r1, #0 + orr r1, #0x02 + orr r1, #0x400 + str r1, [r0] + + mov r0, #0 + // invalidate caches + mcr p15, 0, r0, c7, c7, 0 + // invalidate tlb + mcr p15, 0, r0, c8, c7, 0 + // data sync barrier + mcr p15, 0, r0, c7,c10, 4 + + // set domains + mov r2, #0x01 + mcr p15, 0, r2, c3, c0, 0 + + ldr r0, =0x4000 + // Give the pagetable addr to the MMU + mcr p15, 0, r0, c2, c0, 0 // Table 0 + mcr p15, 0, r0, c2, c0, 1 // Table 1 + + // infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf#page=193 + // Set up that we use half sized page tables (one for kernel one for userspace) + eor r0, r0, r0 // Zero r0 + ADD r0, #1 // Set N to 1 meaning we are using pagetables of 8KiB in size. + mcr p15, 0, r0, c2, c0, 2 // Enable page walks on both page tables. + + mrc p15, 0, r3, c1, c0, 0 + orr r3, #0x800000 + orr r3, r3, #0x1 // Enable MMU bit + mcr p15, 0, r3, c1, c0, 0 // Set p15 + + pop {r0-r11} + ldr sp, =KERNEL_STACK_TOP // Set the kernel/SVC stack + push {r0-r11} + + // Setup + bl stacks + + // Jumpt to the start of the kernel + bl start + +loop: + WFI + B loop + + +.bss +EARLY_KERNEL_STACK_BOTTOM: + .space 128 +EARLY_KERNEL_STACK_TOP: diff --git a/kernel/src/drivers/chipset/bcm2835/bcm2835.c b/kernel/src/drivers/chipset/bcm2835/bcm2835.c new file mode 100644 index 00000000..0c353e4f --- /dev/null +++ b/kernel/src/drivers/chipset/bcm2835/bcm2835.c @@ -0,0 +1 @@ +#include diff --git a/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h b/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h new file mode 100644 index 00000000..dfed5272 --- /dev/null +++ b/kernel/src/drivers/chipset/bcm2835/include/bcm2835.h @@ -0,0 +1,2 @@ +// TODO: Implement. +// We want to have bcm2835 for being able to boot on an actual Pi Zero/B+ diff --git a/kernel/src/drivers/chipset/bcm2836/bcm2836.c b/kernel/src/drivers/chipset/bcm2836/bcm2836.c new file mode 100644 index 00000000..1394dc08 --- /dev/null +++ b/kernel/src/drivers/chipset/bcm2836/bcm2836.c @@ -0,0 +1,40 @@ +// https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf +#include +#include +#include +#include +#include + +void bcm2836_irq_handler() { + volatile const uint32_t pending = bcm2836_registers_base->Core0IRQSource; + + switch (pending) { + // Generic timers + case PHYSICAL_SECURE_TIMER: + timer_handle_interrupt(); + break; + } +} + +void bcm2836_fiq_handler() {} + +void bcm2836_init() { + chipset.schedule_timer_periodic = &bcm2836_schedule_timer_periodic; + chipset.schedule_timer_once = &bcm2836_schedule_timer_once; + chipset.deschedule_timer = &bcm2836_deschedule_timer; + chipset.uart_putc = &bcm2836_uart_putc; + chipset.uart_on_message = &bcm2836_uart_on_message; + chipset.handle_irq = &bcm2836_irq_handler; + chipset.handle_fiq = &bcm2836_fiq_handler; + chipset.late_init = &bcm2836_late_init; + + bcm2836_registers_base = + (struct BCM2836Registers *)vm2_map_peripheral(BCM2836_REGISTERS_PHYSICAL_BASE, 1); + bcm2836_peripheral_base = vm2_map_peripheral(BCM2836_PERIPHERALS_PHYSICAL_BASE, 4); + + bcm2836_uart_init(); +} + +void bcm2836_late_init() { + bcm2836_timer_init(); +} diff --git a/kernel/src/drivers/chipset/bcm2836/include/bcm2836.h b/kernel/src/drivers/chipset/bcm2836/include/bcm2836.h new file mode 100644 index 00000000..6ca0f7ba --- /dev/null +++ b/kernel/src/drivers/chipset/bcm2836/include/bcm2836.h @@ -0,0 +1,116 @@ +// Data sheet: https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf + +#ifndef BCM2836_H +#define BCM2836_H + +#include + +#define BCM2836_REGISTERS_PHYSICAL_BASE 0x40000000 +#define BCM2836_PERIPHERALS_PHYSICAL_BASE 0x3F000000 + +/* + * Implementation of chipset driver interface for BCM2836 + */ + +// Starts at memory address 0x4000_0000 +typedef struct BCM2836Registers { + uint32_t ControlRegister; + uint32_t __unused1; + uint32_t CoreTimerPrescaler; + uint32_t GPUInterruptsRouting; + uint32_t PerformanceMonitorRoutingSet; + uint32_t PerformanceMonitorRoutingClear; + uint32_t __unused2; + uint32_t CoreTimerAccessLS32Bits; + uint32_t CoreTimerAccessMS32Bits; + uint32_t LocalInterupts0Routing; + uint32_t __LocalInterupts8Routing __attribute__((deprecated)); // Deprecated + uint32_t AxiOutstandingCounters; + uint32_t AxiOutstandingIRQ; + uint32_t LocalTimerControlAndStatus; + uint32_t LocalTimerWriteFlags; + uint32_t __unused3; + uint32_t Core0TimersInterruptControl; + uint32_t Core1TimersInterruptControl; + uint32_t Core2TimersInterruptControl; + uint32_t Core3TimersInterruptControl; + uint32_t Core0MailboxInterruptControl; + uint32_t Core1MailboxInterruptControl; + uint32_t Core2MailboxInterruptControl; + uint32_t Core3MailboxInterruptControl; + uint32_t Core0IRQSource; + uint32_t Core1IRQSource; + uint32_t Core2IRQSource; + uint32_t Core3IRQSource; + uint32_t Core0FIQSource; + uint32_t Core1FIQSource; + uint32_t Core2FIQSource; + uint32_t Core3FIQSource; + uint32_t Core0Mailbox0WriteSet; + uint32_t Core0Mailbox1WriteSet; + uint32_t Core0Mailbox2WriteSet; + uint32_t Core0Mailbox3WriteSet; + uint32_t Core1Mailbox0WriteSet; + uint32_t Core1Mailbox1WriteSet; + uint32_t Core1Mailbox2WriteSet; + uint32_t Core1Mailbox3WriteSet; + uint32_t Core2Mailbox0WriteSet; + uint32_t Core2Mailbox1WriteSet; + uint32_t Core2Mailbox2WriteSet; + uint32_t Core2Mailbox3WriteSet; + uint32_t Core3Mailbox0WriteSet; + uint32_t Core3Mailbox1WriteSet; + uint32_t Core3Mailbox2WriteSet; + uint32_t Core3Mailbox3WriteSet; + uint32_t Core0Mailbox0ReadClear; + uint32_t Core0Mailbox1ReadClear; + uint32_t Core0Mailbox2ReadClear; + uint32_t Core0Mailbox3ReadClear; + uint32_t Core1Mailbox0ReadClear; + uint32_t Core1Mailbox1ReadClear; + uint32_t Core1Mailbox2ReadClear; + uint32_t Core1Mailbox3ReadClear; + uint32_t Core2Mailbox0ReadClear; + uint32_t Core2Mailbox1ReadClear; + uint32_t Core2Mailbox2ReadClear; + uint32_t Core2Mailbox3ReadClear; + uint32_t Core3Mailbox0ReadClear; + uint32_t Core3Mailbox1ReadClear; + uint32_t Core3Mailbox2ReadClear; + uint32_t Core3Mailbox3ReadClear; +} BCM2836Registers; + +enum InterruptSource { + // nCNTPSIRQ : Secure physical timer event + PHYSICAL_SECURE_TIMER = (1 << 0), + + // nCNTPNSIRQ : Non-secure physical timer event + PHYSICAL_NONSECURE_TIMER = (1 << 1), + + // nCNTHPIRQ: Physical Timer for use in Hypervisor mode. + PHYSICAL_HYPERVISOR_TIMER = (1 << 2), + + // nCNTVIRQ: Virtual Timer for use in Non-secure PL1 modes. + VIRTUAL_NONSECURE_TIMER = (1 << 3), + + MAILBOX_0 = (1 << 4), + MAILBOX_1 = (1 << 5), + MAILBOX_2 = (1 << 6), + MAILBOX_3 = (1 << 7), + + GPU = (1 << 8), + PMU = (1 << 9), + + AXI = (1 << 10), + LOCAL_TIMER = (1 << 11), +}; + +volatile BCM2836Registers * bcm2836_registers_base; + +void bcm2836_init(); +void bcm2836_late_init(); + +volatile struct BCM2836Registers * bcm2836_registers_base; +size_t bcm2836_peripheral_base; + +#endif diff --git a/kernel/src/drivers/chipset/bcm2836/include/timer.h b/kernel/src/drivers/chipset/bcm2836/include/timer.h new file mode 100644 index 00000000..26db06c9 --- /dev/null +++ b/kernel/src/drivers/chipset/bcm2836/include/timer.h @@ -0,0 +1,21 @@ +#ifndef TIMER_BCM2836_H +#define TIMER_BCM2836_H + +#include +#include + +/* + * ARM Generic Timer driver for BCM2836 + */ + +void bcm2836_timer_init(); + +void timer_handle_interrupt(); + +TimerHandle bcm2836_schedule_timer_once(TimerCallback callback, uint32_t delay_ms); + +TimerHandle bcm2836_schedule_timer_periodic(TimerCallback callback, uint32_t delay_ms); + +void bcm2836_deschedule_timer(TimerHandle handle); + +#endif diff --git a/kernel/src/drivers/chipset/bcm2836/include/uart.h b/kernel/src/drivers/chipset/bcm2836/include/uart.h new file mode 100644 index 00000000..30ffecd1 --- /dev/null +++ b/kernel/src/drivers/chipset/bcm2836/include/uart.h @@ -0,0 +1,38 @@ +#ifndef UART_BCM2836_H +#define UART_BCM2836_H + +#include +#include + +// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf +// Section 3.2: Summary of registers +// https://balau82.wordpress.com/2010/11/30/emulating-arm-pl011-serial-ports/ +// This struct is memory mapped. I call them registers but they all live in memory. +typedef volatile struct BCM2836UartInterface { + uint32_t DR; // Data Register + uint32_t RSR_ECR; // Receive Status Register / Error Clear Register + uint8_t reserved1[0x10]; // Reserved + const uint32_t FR; // Flag Register + uint8_t reserved2[0x4]; // Reserved + uint32_t LPR; // IrDA low power counter Register + uint32_t IBRD; // Integer Baud Rate Register + uint32_t FBRD; // Fractional Baud Rate Register + uint32_t LCR_H; // Line Control Register + uint32_t CR; // Control Register + uint32_t IFLS; // Interrupt FIFO Level Select Register + uint32_t IMSC; // Interrupt Mask Set/Clear Register + const uint32_t RIS; // Raw Interrupt Status Register + const uint32_t MIS; // Masked Interrupt Status Register + uint32_t ICR; // Interrupt Clear Register + uint32_t DMACR; // DMA Control Register +} BCM2836UartInterface; + +void bcm2836_uart_init(); + +void uart_write_byte(BCM2836UartInterface * interface, volatile uint8_t value); + +void bcm2836_uart_putc(char c, int uartchannel); + +void bcm2836_uart_on_message(UartCallback callback, int uartchannel); + +#endif diff --git a/kernel/src/drivers/chipset/bcm2836/test/timer_test.c b/kernel/src/drivers/chipset/bcm2836/test/timer_test.c new file mode 100644 index 00000000..b907b33d --- /dev/null +++ b/kernel/src/drivers/chipset/bcm2836/test/timer_test.c @@ -0,0 +1,53 @@ +#include +#include + +static int callback_count_1; +static int callback_count_2; + +static void test_callback_1() { + callback_count_1++; +} + +static void test_callback_2() { + callback_count_2++; +} + +TEST_CREATE(test_timer_cb_called, { + callback_count_1 = 0; + + bcm2836_schedule_timer_once(test_callback_1, 50); + DEBUG("If the test gets stuck here, the timer callback was never called"); + while (callback_count_1 != 1); + PASS(); +}) + +TEST_CREATE(test_timer_cancel, { + callback_count_1 = 0; + + TimerHandle const handle = bcm2836_schedule_timer_once(test_callback_1, 50); + bcm2836_deschedule_timer(handle); + ASSERT_EQ(callback_count_1, 0); +}) + +TEST_CREATE(test_timer_periodic_cb_called, { + callback_count_1 = 0; + + TimerHandle const handle = bcm2836_schedule_timer_periodic(test_callback_1, 50); + DEBUG("If the test gets stuck here, the timer callback was not called the required number of times"); + while (callback_count_1 != 10); + bcm2836_deschedule_timer(handle); + PASS(); +}) + +TEST_CREATE(test_timer_order, { + callback_count_1 = 0; + callback_count_2 = 0; + + bcm2836_schedule_timer_once(test_callback_1, 50); + bcm2836_schedule_timer_once(test_callback_2, 100); + DEBUG("If the test gets stuck here, one of the timer callbacks was never called"); + while (callback_count_1 != 1); + ASSERT_EQ(callback_count_2, 0); + while (callback_count_2 != 1); + PASS(); +}) diff --git a/kernel/src/drivers/chipset/bcm2836/timer.c b/kernel/src/drivers/chipset/bcm2836/timer.c new file mode 100644 index 00000000..43de5671 --- /dev/null +++ b/kernel/src/drivers/chipset/bcm2836/timer.c @@ -0,0 +1,221 @@ +#include +#include +#include +#include +#include +#include +#include + +typedef struct ScheduledTimer { + uint64_t scheduled_count; + TimerHandle handle; + TimerCallback callback; + uint32_t periodic_delay; +} ScheduledTimer; + +typedef union LittleEndianUint64 { + uint64_t dword; + struct { + uint32_t low_word; + uint32_t high_word; + }; +} LittleEndianUint64; + +// Internal implementation functions +static uint32_t get_frequency(); +static void unmask_and_enable_timer(); +static void mask_and_enable_timer(); +static uint64_t get_phy_count(); +static int32_t get_phy_timer_val(); +static void set_phy_timer_val(int32_t); +static uint64_t get_phy_timer_cmp_val(); +static void set_phy_timer_cmp_val(uint64_t); +static ScheduledTimer * get_prq_node_data(prq_node *); +static TimerHandle schedule_timer(TimerCallback, uint32_t, bool); + +static prq_handle * scheduled_timers; + +/* + * Gives the frequency of the counter in Hz + */ +static inline uint32_t get_frequency() { + uint32_t val; + // Read CNTFRQ + asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r"(val)); + return val; +} + +static inline void unmask_and_enable_timer() { + // Disable output mask, enable timer + static const uint32_t cntp_ctl = 0b01; + // Write CNTP_CTL + asm volatile("mcr p15, 0, %0, c14, c2, 1" ::"r"(cntp_ctl)); +} + +static inline void mask_and_enable_timer() { + // Enable output mask, enable timer + static const uint32_t cntp_ctl = 0b11; + // Write CNTP_CTL + asm volatile("mcr p15, 0, %0, c14, c2, 1" ::"r"(cntp_ctl)); +} + +static inline uint64_t get_phy_count() { + LittleEndianUint64 val; + // Read CNTPCT + asm volatile("mrrc p15, 0, %0, %1, c14" : "=r"(val.low_word), "=r"(val.high_word)); + return val.dword; +} + +static inline int32_t get_phy_timer_val() { + int32_t val; + // Read CNTP_TVAL + asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r"(val)); + return val; +} + +static inline void set_phy_timer_val(int32_t val) { + // Write CNTP_TVAL + asm volatile("mcr p15, 0, %0, c14, c2, 0" ::"r"(val)); +} + +static inline uint64_t get_phy_timer_cmp_val() { + LittleEndianUint64 val; + // Read CNTP_CVAL + asm volatile("mrrc p15, 2, %0, %1, c14" : "=r"(val.low_word), "=r"(val.high_word)); + return val.dword; +} + +static inline void set_phy_timer_cmp_val(uint64_t val) { + const LittleEndianUint64 le_val = (LittleEndianUint64)val; + // Write CNTP_CVAL + asm volatile("mcrr p15, 2, %0, %1, c14" ::"r"(le_val.low_word), "r"(le_val.high_word)); +} + +static inline ScheduledTimer * get_prq_node_data(prq_node * node) { + return (ScheduledTimer *)node->data; +} + +void bcm2836_timer_init() { + const uint32_t freq = get_frequency(); + INFO("System counter frequency: %u kHz\n", freq / 1000); + + bcm2836_registers_base->Core0TimersInterruptControl = PHYSICAL_SECURE_TIMER; + + // Init priority queue + scheduled_timers = prq_create(); + + // Initially there are no timers set yet, so the interrupt is masked + mask_and_enable_timer(); +} + +void timer_handle_interrupt() { + volatile const uint64_t current_count = get_phy_count(); + + // Begin of critical section, disable timer interrupts + bcm2836_registers_base->Core0TimersInterruptControl = 0; + + // Process all timers that are not in the future, if any + prq_node * next_timer_node = prq_peek(scheduled_timers); + while (next_timer_node != NULL && + get_prq_node_data(next_timer_node)->scheduled_count <= current_count) { + + prq_dequeue(scheduled_timers); + ScheduledTimer * const next_timer = get_prq_node_data(next_timer_node); + + next_timer->callback(); + + // If the timer is not periodic, it is removed + if (next_timer->periodic_delay == 0) { + kfree(next_timer); + prq_free_node(next_timer_node); + } + // If the timer is periodic, it is updated and added to the queue again + else { + // TODO: Avoid duplicating code in `schedule_timer` + const uint64_t scheduled_count = next_timer->scheduled_count; + next_timer->scheduled_count = scheduled_count + next_timer->periodic_delay; + assert(scheduled_count <= INT32_MAX); + next_timer_node->priority = scheduled_count; + + prq_enqueue(scheduled_timers, next_timer_node); + } + + next_timer_node = prq_peek(scheduled_timers); + } + + // If there are no more scheduled timers in queue, mask interrupts until one is added again + if (next_timer_node == NULL) { + mask_and_enable_timer(); + } + // If there still are, set compare val to next one + else { + set_phy_timer_cmp_val(get_prq_node_data(next_timer_node)->scheduled_count); + } + + // End of critical section, re-enable timer interrupts + bcm2836_registers_base->Core0TimersInterruptControl = PHYSICAL_SECURE_TIMER; +} + +static TimerHandle schedule_timer(TimerCallback callback, uint32_t delay_ms, bool periodic) { + assert(callback != NULL); + assert(delay_ms > 0); + + const uint64_t count_offset = (get_frequency() / 1000) * delay_ms; + volatile const uint64_t scheduled_count = get_phy_count() + count_offset; + + ScheduledTimer * const new_timer = kmalloc(sizeof(ScheduledTimer)); + prq_node * const new_timer_node = prq_create_node(); + + new_timer->scheduled_count = scheduled_count; + new_timer->callback = callback; + assert(sizeof(TimerHandle) >= sizeof(prq_node *)); + new_timer->handle = (TimerHandle)new_timer_node; + // 0 means the timer is not periodic + new_timer->periodic_delay = periodic ? count_offset : 0; + // TODO: Find better way of doing this + assert(scheduled_count <= INT32_MAX); + new_timer_node->priority = scheduled_count; + new_timer_node->data = new_timer; + + // Begin of critical section, disable timer interrupts + bcm2836_registers_base->Core0TimersInterruptControl = 0; + + prq_enqueue(scheduled_timers, new_timer_node); + + set_phy_timer_cmp_val(get_prq_node_data(prq_peek(scheduled_timers))->scheduled_count); + + // Unmask interrupt if not already so + unmask_and_enable_timer(); + + // End of critical section, re-enable timer interrupts + bcm2836_registers_base->Core0TimersInterruptControl = PHYSICAL_SECURE_TIMER; + + return new_timer->handle; +} + +TimerHandle bcm2836_schedule_timer_once(TimerCallback callback, uint32_t delay_ms) { + return schedule_timer(callback, delay_ms, false); +} + +TimerHandle bcm2836_schedule_timer_periodic(TimerCallback callback, uint32_t delay_ms) { + return schedule_timer(callback, delay_ms, true); +} + +void bcm2836_deschedule_timer(TimerHandle handle) { + assert(sizeof(prq_node *) >= sizeof(TimerHandle)); + prq_node * const timer_node = (prq_node *)handle; + + prq_remove(scheduled_timers, timer_node); + kfree(get_prq_node_data(timer_node)); + prq_free_node(timer_node); + + prq_node * const next_timer_node = prq_peek(scheduled_timers); + // If there are no more scheduled timers in queue, mask interrupts until one is added again + if (next_timer_node == NULL) { + mask_and_enable_timer(); + } + // If there still are, set compare val to next one + else { + set_phy_timer_cmp_val(get_prq_node_data(next_timer_node)->scheduled_count); + } +} diff --git a/kernel/src/drivers/chipset/bcm2836/uart.c b/kernel/src/drivers/chipset/bcm2836/uart.c new file mode 100644 index 00000000..51e9f846 --- /dev/null +++ b/kernel/src/drivers/chipset/bcm2836/uart.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include +#include + +/* +// raspberry pi zero, 1, b+ etc +volatile UartInterface * const UART0_ADDRESS = (volatile UartInterface *)0x20201000; +volatile UartInterface * const UART1_ADDRESS = (volatile UartInterface *)0x20202000; +volatile UartInterface * const UART2_ADDRESS = (volatile UartInterface *)0x20203000; + +// raspberry pi 4: +volatile UartInterface * const UART0_ADDRESS = (volatile UartInterface *)0xfe201000; +volatile UartInterface * const UART1_ADDRESS = (volatile UartInterface *)0xfe202000; +volatile UartInterface * const UART2_ADDRESS = (volatile UartInterface *)0xfe203000; + VersatilePB +volatile UartInterface * const UART0_ADDRESS = (volatile UartInterface *)0x101f1000; +volatile UartInterface * const UART1_ADDRESS = (volatile UartInterface *)0x101f2000; +volatile UartInterface * const UART2_ADDRESS = (volatile UartInterface *)0x101f3000; +*/ + + +// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf +// uart flag register masks +// (FR) +#define RI (1 << 8) // Ring Indicator +#define TXFE (1 << 7) // Transmit fifo empty +#define RXFF (1 << 6) // Receive fifo full +#define TXFF (1 << 5) // Transmit fifo full +#define RXFE (1 << 4) // Receive fifo empty +#define BUSY (1 << 3) // UART busy, set while uart is sending something +#define DCD (1 << 2) // Data carrier detect +#define DSR (1 << 1) // Data set ready +#define CTS (1 << 0) // Clear to send + +// Uart interrupt masks. When a mask is set, this action causes an interrupt +// (IMSC) +#define OEIM (1 << 10) // Overrun error +#define BEIM (1 << 9) // Break error +#define PEIM (1 << 8) // Parity error +#define FEIM (1 << 7) // Framing error +#define RTIM (1 << 6) // Receive timeout +#define TXIM (1 << 5) // Transmit +#define RXIM (1 << 4) // Receive +#define DSRMIM (1 << 3) // nUARTDSR Modem +#define DCDMIM (1 << 2) // nUARTDCD Modem +#define CTCMIM (1 << 1) // nUARTCTS Modem +#define RIMIM (1 << 0) // nUARTRI Modem + +// (CR) +//#define CTSEn () // CTS Hardware Control Enable + +static BCM2836UartInterface * BCM2836_UART0_ADDRESS; +static BCM2836UartInterface * BCM2836_UART1_ADDRESS; +static BCM2836UartInterface * BCM2836_UART2_ADDRESS; +static BCM2836UartInterface * BCM2836_UART3_ADDRESS; + +void bcm2836_uart_init() { + BCM2836_UART0_ADDRESS = (BCM2836UartInterface *)(bcm2836_peripheral_base + 0x201000); + BCM2836_UART1_ADDRESS = (BCM2836UartInterface *)(bcm2836_peripheral_base + 0x202000); + BCM2836_UART2_ADDRESS = (BCM2836UartInterface *)(bcm2836_peripheral_base + 0x203000); + BCM2836_UART3_ADDRESS = (BCM2836UartInterface *)(bcm2836_peripheral_base + 0x204000); +} + +void uart_write_byte(volatile BCM2836UartInterface * interface, volatile uint8_t value) { + // while (interface->FR & TXFF ) { + // asm volatile ("nop"); + // } + interface->DR = (uint32_t)value; +} + +void bcm2836_uart_putc(char c, int uartchannel) { + if (uartchannel >= 4) { uartchannel = 0; } + + switch (uartchannel) { + case 0: + return uart_write_byte(BCM2836_UART0_ADDRESS, c); + case 1: + return uart_write_byte(BCM2836_UART1_ADDRESS, c); + case 2: + return uart_write_byte(BCM2836_UART2_ADDRESS, c); + case 3: + return uart_write_byte(BCM2836_UART3_ADDRESS, c); + default: + panic(); + } +} + +void bcm2836_uart_on_message(UartCallback callback, int uartchannel) {} diff --git a/kernel/src/drivers/chipset/chipset.c b/kernel/src/drivers/chipset/chipset.c new file mode 100644 index 00000000..8b2ce4be --- /dev/null +++ b/kernel/src/drivers/chipset/chipset.c @@ -0,0 +1,35 @@ + +#include +#include +#include +#include +#include + +// We use putc (and printf) before the chipset is initialized already. +// This stub makes sure that nothing crashes if you do that. +void uart_putc_stub(char c __attribute__((unused)), int channel __attribute__((unused))) {} + +ChipsetInterface chipset = { + .uart_putc = uart_putc_stub // Stub putc +}; + +void init_chipset() { + HardwareInfo * info = get_hardwareinfo(); + + memset(&chipset, 0, sizeof(ChipsetInterface)); + + switch (info->boardType) { + case RaspBerryPiTwo: + bcm2836_init(); + break; + default: { + FATAL("Board type not supported for interrupts \n"); + } + } + + for (size_t i = 0; i < sizeof(ChipsetInterface) / sizeof(uint32_t); i++) { + if (((uint32_t **)&chipset)[i] == NULL) { + FATAL("Chipset did not satisfy the required interface. Missing field %i\n", i); + } + } +} diff --git a/kernel/src/drivers/chipset/include/chipset.h b/kernel/src/drivers/chipset/include/chipset.h new file mode 100644 index 00000000..c754e91b --- /dev/null +++ b/kernel/src/drivers/chipset/include/chipset.h @@ -0,0 +1,51 @@ +#ifndef INTERRUPT_H +#define INTERRUPT_H + +#include +#include + +/* + * Abstract chipset driver interface + */ + +void init_chipset(); +void uart_putc(char c, int channel); + +// A timer handle is an identifier for a timer so it can be descheduled later. +// These handles must be unique. +typedef size_t TimerHandle; +typedef void (*TimerCallback)(); + +typedef void (*UartCallback)(char c); + +typedef struct ChipsetInterface { + /// Timer Functions + TimerHandle (*schedule_timer_periodic)(TimerCallback callback, uint32_t ms); + TimerHandle (*schedule_timer_once)(TimerCallback callback, uint32_t ms); + void (*deschedule_timer)(TimerHandle handle); + + /// UART Functions + // Prints a character to a uart channel. + // The definition of a channel is pretty open to interpretation + // but what must be guaranteed is that channel 0 is the default channel + // and in normal operation should always just work. Other channels might not exist. + // If a user requests to print on a non existent channel, the output must be printed on + // channel 0. + void (*uart_putc)(char c, int uartchannel); + + // The callback given to this function is called any time a uart message + // is received on the channel. The same rules apply as for puts. When a channel + // is requested that does not exist, input from channel zero shall be given to this callback. + void (*uart_on_message)(UartCallback callback, int uartchannel); + + void (*handle_irq)(); + void (*handle_fiq)(); + + // Called for every chipset after interrupts and dynamic memory has been enabled + // So the chipset can do some more initialization. + void (*late_init)(); +} ChipsetInterface; + +ChipsetInterface chipset; + +#endif diff --git a/kernel/include/drivers/mmci.h b/kernel/src/drivers/mmci/include/mmci.h similarity index 81% rename from kernel/include/drivers/mmci.h rename to kernel/src/drivers/mmci/include/mmci.h index 19556bda..4c440985 100644 --- a/kernel/include/drivers/mmci.h +++ b/kernel/src/drivers/mmci/include/mmci.h @@ -14,12 +14,12 @@ void run_mmci(uint32_t cmd, uint32_t args); uint32_t read_mmci(uint32_t target); int status(); -int push_bytes(void* buffer); -int pull_bytes(void* buffer); +int push_bytes(void * buffer); +int pull_bytes(void * buffer); int init_sd(); uint32_t sd_capacity(); -int sd_transmit(void* buffer, uint32_t address); -int sd_receive(void* buffer, uint32_t address); +int sd_transmit(void * buffer, uint32_t address); +int sd_receive(void * buffer, uint32_t address); int clear(); int status(); diff --git a/kernel/src/drivers/mmci/mmci.c b/kernel/src/drivers/mmci/mmci.c new file mode 100644 index 00000000..70626678 --- /dev/null +++ b/kernel/src/drivers/mmci/mmci.c @@ -0,0 +1,347 @@ +/** + * @file MMCI (Multimedia Card Interface) Driver + * + * @author Joseph Bourque, Matt Davidson, Weston Selleck \n + * QC and Support: Lane Kolbly + * + * @version 1.0 + * + * @section DESCRIPTION + * + * The driver for the SD card; provides an interface between the + * operating system and the SD card controller. Currently set up + * to use FIFO for input and output + * + * TODO: Need to implement DMA support at some time in the future + * (Not needed until multi-kthread implemented) + * + * Completed On: 4/20/2015 Last Updated: 5/5/2015 + */ +#include +#include + +// MMCI Definitions - Used to access SD card registers; DO NOT CHANGE! +#define MMCI_BASE 0x10005000 +#define CMD 0x00C +#define DCTRL 0x02C +#define FIFO 0x080 +#define FIFO_CNT 0x048 +#define STATUS 0x34 +#define ARG 0x008 +#define CLR 0x038 +#define RESP_0 0x14 +#define RESP_1 0x18 +#define RESP_2 0x1C +#define RESP_3 0x20 +#define DATA_LEN 0x028 + +// bit shift definitions - Used to modify SD card registers; DO NOT CHANGE! +#define EXE (1 << 10) +#define RESP (1 << 6) +#define LRESP (1 << 7) +#define RCA_MASK 0xFFFF0000 +#define SET_WRITE 1 | (9 << 4) +#define SET_READ 3 | (9 << 4) +#define DISABLE 0x0 | (9 << 4) +#define READ_CNT (read_mmci(STATUS) & (1 << 21)) +#define WRITE_CNT (read_mmci(FIFO_CNT) > 0) +#define STATUS_ERR 0x3F + + +/** + * Initialize SD Card Method + * + * Initializes SD card putting it in the transfer state; this should + * be called when the kernel boots up; readies the SD card for + * data transfer. Right now this function chooses the first available + * SD card. + * + * TODO: Add to/split up this function in order to work with multiple + * SD cards i.e. let the user set up additional SD cards past + * the first + * + * @return + * + * If the SD card was initialized correctly; this returns 0; otherwise + * this will return a negative integer value based on the value stored + * in the status register + */ + +int init_sd() { + asm volatile("cpsie if"); + int rca = 0; + + // let the SD card know you're about to call one of the ACMD commands + run_mmci(CMD, 55 | EXE); + + // Set up the argument register for the next command + run_mmci(ARG, 123); + + // Set & Execute the ACMD set voltage command + run_mmci(CMD, 41 | EXE); + + // Set & Execute the get card identifier command + run_mmci(CMD, 2 | EXE | RESP | LRESP); + + // Set & execute the obtain RCA command; this will allow you + // to identifiy and select a particular SD card to read/write + // to in the event you have more than one card + run_mmci(CMD, 3 | EXE | RESP); + + // obtain RCA address and mask out the status bits + rca = (read_mmci(RESP_0) & RCA_MASK); + + // Load masked RCA address into the argument register + run_mmci(ARG, rca); + + // Run the select card command and point it at the card loaded + // in the argument register + run_mmci(CMD, 7 | EXE | RESP); + + // Set the data length register to 512 to indicate the amount + // amount of data to be moved is 512 bytes + // Note: This sets the value of FIFO count as well + run_mmci(DATA_LEN, SD_BLOCK_SIZE); + + // Eventually print some status message here if the SD card + // failed to initialize properly but for now just print + // that it was loaded OK + kprintf("\nSD card ready for transfer\n"); + + return status(); +} + +/** + * SD Capacity Method + * + * Returns the maximum filled of the SD card in bytes; for our + * current needs it computes the size statically + * + * TODO: Eventually this needs to be set up to calculate the size + * of the SD card dynamically to account for different sized + * SD cards + * + * @return Returns the size of the SD card (in bytes) + */ +uint32_t sd_capacity() { + return 128 * 1024 * 1024; +} + +/** + * Transmit to SD Card Method + * + * Writes the contents of the FIFO buffer to the SD card; Writes + * A single block at a time. + * + * @param + * + * void* buffer - Holds a single block of data and treats it as a + bitstream + * @param + * + * uint32_t address - Holds the address of the block of the SD card + * to write to; the address is a multiple of the + * block size + * @return + * + * If the write was successful this returns 0; otherwise + * this returns a negative integer based on the status + * flags set + */ +int sd_transmit(void * buffer, uint32_t address) { + // Set the block length on the SD card + run_mmci(ARG, SD_BLOCK_SIZE); + run_mmci(CMD, 16 | EXE | RESP); + + // Set up the write command + run_mmci(ARG, address); + run_mmci(CMD, 24 | EXE | RESP); + push_bytes(buffer); + + // Return that write succeeded for now + return status(); +} + +/** + * Receive from the SD Card Method + * + * Reads the contents of the FIFO buffer from the SD card; reads + * a single block at a time from the passed address and stores it + * in the passed buffer + * + * @param + * + * void* buffer - Serves a a recepticle to place the information + * read from disk + * @param + * + * uint32_t address - stores the address on disk to read from + * disk addresses are a mulitple of block + * size + * + * @return + * + * Returns 0 if the read was successful; otherwise returns a + * negative integer based on the value stored in the status + * register + */ +int sd_receive(void * buffer, uint32_t address) { + // Clear out FIFO and set to read + run_mmci(DCTRL, DISABLE); + run_mmci(DCTRL, SET_READ); + // Set address to read from & send the command to read + run_mmci(ARG, address); + run_mmci(CMD, 17 | EXE | RESP); + + pull_bytes(buffer); + + // Return that read succeeded for now + return status(); +} + +/** + * Clear Method + * + * Resets all non-dynamic status flags + * + * @return + * + * Returns 0 if the clear was successful; otherwise returns a negative + * integer based off the value stored in the status register + */ +int clear() { + // Return that the clear succeeded for now + // Clear all status flags + run_mmci(CLR, 0x2FF); + return status(); +} + + +///// Helper Functions ///// Helper Functions ///// Helper Functions ///// + + +/** + * Push Bytes + * + * Helper method for the sd_transmit method; pushes bits into + * the fifo buffer using the passed buffer space + * + * @param + * + * void* buffer - An address which represents 1 block of data; + * provides a space for FIFO to interact with + * when writing to the SD card + * + * @return + * + * Returns 0 if the write was successful; otherwise returns a + * negative integer based on the value stored in the status + * register + */ +int push_bytes(void * buffer) { + // Clear out FIFO and set to write + run_mmci(DCTRL, DISABLE); + run_mmci(DCTRL, SET_WRITE); + int i = 0; + while (WRITE_CNT) { + run_mmci(FIFO, ((uint32_t *)buffer)[i]); + i++; + } + + // Return that the push succeeded for now + return status(); +} + +/** + * Pull Bytes Method + * + * Helper function for the sd_recieve method; pulls bits out of + * the FIFO buffer and stores them in the buffer passed into + * the function (buffer represents 1 block of data) + * + * @param + * + * void* buffer - An address in memory representing 1 block + * of data; provides a space for FIFO to store + * the result of the read from the SD card + * + * @return + * + * Returns 0 if the read was successful; otherwise returns a + * negative integer based on the value stored in the status + * register + */ +int pull_bytes(void * buffer) { + int i = 0; + while (READ_CNT) { + ((uint32_t *)buffer)[i] = read_mmci(FIFO); + i++; + } + + // Return that the pull succeeded for now + return status(); +} + +/** + * Run MMCI Method + * + * This method is primarily used to run the various mmci commands + * and it does so by using ARM assembly to store a value in register + * corresponding to an MMCI command + * + * @param + * + * uint32_t cmd - Stores the address offset based on the MMCI base + * address for a MMCI command. + * + * @param + * + * uint32_t args - Represents the bits which will actually be set + * on the register when running a specific command + */ +void run_mmci(uint32_t cmd, uint32_t args) { + uint32_t reg_address = MMCI_BASE + cmd; + asm volatile("str %0,[%1]" : : "r"(args), "r"(reg_address)); +} + +/** + * Read MMCI Method + * + * This method is primarily used for getting some response from a MMCI + * register (response register, status register, etc.) + * + * @param + * + * uint32_t target - Passes in the target register to read; represented + * as an offset to the MMCI base address + + * @return + * + * Returns the value stored in the target register as an integer value + */ +uint32_t read_mmci(uint32_t target) { + uint32_t response; + uint32_t reg_address = MMCI_BASE + target; + asm volatile("ldr %0,[%1]" : "=r"(response) : "r"(reg_address)); + return response; +} + +/** + * Status Method + * + * Helper method which handles error detection for the driver; because + * multiple bits can be set due to multiple errors; combine bits where + * neccessary to obtain error code + * + *@return + * + * if no error - will return 0 + * if -1 , error code 0 + * if -2 , error code 1 + * if -3 , error code 0 and 1 + */ +int status() { + uint32_t stat = read_mmci(STATUS); + int error = stat & STATUS_ERR; + return (~error + 1); +} diff --git a/kernel/src/ds/bpf/HashMap.c b/kernel/src/ds/bpf/HashMap.c new file mode 100644 index 00000000..efd0f8bb --- /dev/null +++ b/kernel/src/ds/bpf/HashMap.c @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +/* + * Generic non-thread safe hash map implementation. + * + * Copyright (c) 2019 Facebook + * Copyright (c) 2020 Jonathan Dönszelmann and Victor Roest (Changed for use in course_os) + */ + + +#include "include/HashMap.h" + +#include +#include +#include +/* make sure libbpf doesn't use kernel-only integer typedefs */ +#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 + +/* start with 4 buckets */ +#define HASHMAP_MIN_CAP_BITS 2 + +static void hashmap_add_entry(struct hashmap_entry ** pprev, struct hashmap_entry * entry) { + entry->next = *pprev; + *pprev = entry; +} + +static void hashmap_del_entry(struct hashmap_entry ** pprev, struct hashmap_entry * entry) { + *pprev = entry->next; + entry->next = NULL; +} + +void hashmap__init(struct HashMap * map, + hashmap_hash_fn hash_fn, + hashmap_equal_fn equal_fn, + FreeFunc free_key, + FreeFunc free_data, + void * ctx) { + map->hash_fn = hash_fn; + map->equal_fn = equal_fn; + map->freeData = free_data; + map->freeKey = free_key; + map->ctx = ctx; + + map->buckets = NULL; + map->cap = 0; + map->cap_bits = 0; + map->sz = 0; +} + +struct HashMap * hashmap__new(hashmap_hash_fn hash_fn, + hashmap_equal_fn equal_fn, + FreeFunc free_key, + FreeFunc free_data, + void * ctx) { + struct HashMap * map = kmalloc(sizeof(struct HashMap)); + + if (!map) return NULL; + hashmap__init(map, hash_fn, equal_fn, free_key, free_data, ctx); + return map; +} + +void hashmap__clear(struct HashMap * map) { + struct hashmap_entry *cur, *tmp; + int bkt; + + hashmap__for_each_entry_safe(map, cur, tmp, bkt) { + map->freeKey((void *)cur->key); + map->freeData(cur->value); + kfree(cur); + } + + kfree(map->buckets); + map->cap = map->cap_bits = map->sz = 0; +} + +void hashmap__free(struct HashMap * map) { + if (!map) return; + + hashmap__clear(map); + kfree(map); +} + +size_t hashmap__size(const struct HashMap * map) { + return map->sz; +} + +size_t hashmap__capacity(const struct HashMap * map) { + return map->cap; +} + +static bool hashmap_needs_to_grow(struct HashMap * map) { + /* grow if empty or more than 75% filled */ + return (map->cap == 0) || ((map->sz + 1) * 4 / 3 > map->cap); +} + +static int hashmap_grow(struct HashMap * map) { + struct hashmap_entry ** new_buckets; + struct hashmap_entry *cur, *tmp; + size_t new_cap_bits, new_cap; + size_t h; + int bkt; + + new_cap_bits = map->cap_bits + 1; + if (new_cap_bits < HASHMAP_MIN_CAP_BITS) new_cap_bits = HASHMAP_MIN_CAP_BITS; + + new_cap = 1UL << new_cap_bits; + new_buckets = kcalloc(new_cap, sizeof(new_buckets[0])); + if (!new_buckets) return -1; + + hashmap__for_each_entry_safe(map, cur, tmp, bkt) { + h = hash_bits(map->hash_fn(cur->key, map->ctx), new_cap_bits); + hashmap_add_entry(&new_buckets[h], cur); + } + + map->cap = new_cap; + map->cap_bits = new_cap_bits; + kfree(map->buckets); + map->buckets = new_buckets; + + return 0; +} + +static bool hashmap_find_entry(const struct HashMap * map, + const void * key, + size_t hash, + struct hashmap_entry *** pprev, + struct hashmap_entry ** entry) { + struct hashmap_entry *cur, **prev_ptr; + + if (!map->buckets) return false; + + for (prev_ptr = &map->buckets[hash], cur = *prev_ptr; cur; + prev_ptr = &cur->next, cur = cur->next) { + if (map->equal_fn(cur->key, key, map->ctx)) { + if (pprev) *pprev = prev_ptr; + *entry = cur; + return true; + } + } + + return false; +} + +int hashmap__insert(struct HashMap * map, + const void * key, + void * value, + enum hashmap_insert_strategy strategy, + const void ** old_key, + void ** old_value) { + struct hashmap_entry * entry; + size_t h; + int err; + + if (old_key) *old_key = NULL; + if (old_value) *old_value = NULL; + + h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); + if (strategy != HASHMAP_APPEND && hashmap_find_entry(map, key, h, NULL, &entry)) { + if (old_key) *old_key = entry->key; + if (old_value) *old_value = entry->value; + + if (strategy == HASHMAP_SET || strategy == HASHMAP_UPDATE) { + entry->key = key; + entry->value = value; + return 0; + } else if (strategy == HASHMAP_ADD) { + return -1; + } + } + + if (strategy == HASHMAP_UPDATE) return -1; + + if (hashmap_needs_to_grow(map)) { + err = hashmap_grow(map); + if (err) { return err; } + + h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); + } + + entry = kmalloc(sizeof(struct hashmap_entry)); + if (!entry) return -1; + + + entry->key = key; + entry->value = value; + hashmap_add_entry(&map->buckets[h], entry); + + map->sz++; + + return 0; +} + +bool hashmap__find(const struct HashMap * map, const void * key, void ** value) { + struct hashmap_entry * entry; + size_t h; + + h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); + if (!hashmap_find_entry(map, key, h, NULL, &entry)) return false; + + if (value) *value = entry->value; + return true; +} + +bool hashmap__delete(struct HashMap * map, + const void * key, + const void ** old_key, + void ** old_value) { + struct hashmap_entry **pprev, *entry; + size_t h; + + h = hash_bits(map->hash_fn(key, map->ctx), map->cap_bits); + if (!hashmap_find_entry(map, key, h, &pprev, &entry)) return false; + + if (old_key) *old_key = entry->key; + if (old_value) *old_value = entry->value; + + hashmap_del_entry(pprev, entry); + kfree(entry); + map->sz--; + + return true; +} diff --git a/kernel/src/ds/bpf/include/HashMap.h b/kernel/src/ds/bpf/include/HashMap.h new file mode 100644 index 00000000..dd466eea --- /dev/null +++ b/kernel/src/ds/bpf/include/HashMap.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ + +/* + * Generic non-thread safe hash map implementation. + * + * Copyright (c) 2019 Facebook + * Copyright (c) 2020 Jonathan Dönszelmann and Victor Roest (Changed for integration in course_os) + */ +#ifndef __LIBBPF_HASHMAP_H +#define __LIBBPF_HASHMAP_H + +#include +#include +#include + + +static inline size_t hash_bits(size_t h, int bits) { + /* shuffle bits and return requested number of upper bits */ + return (size_t)(h * 11400714819323198485llu) >> (MACHINE_WORDSIZE - bits); +} + +typedef size_t (*hashmap_hash_fn)(const void * key, void * ctx); +typedef bool (*hashmap_equal_fn)(const void * key1, const void * key2, void * ctx); + +struct hashmap_entry { + const void * key; + void * value; + struct hashmap_entry * next; +}; + +typedef struct HashMap { + hashmap_hash_fn hash_fn; + hashmap_equal_fn equal_fn; + void * ctx; + + FreeFunc freeData; + FreeFunc freeKey; + + struct hashmap_entry ** buckets; + size_t cap; + size_t cap_bits; + size_t sz; +} HashMap; + +#define HASHMAP_INIT(hash_fn, equal_fn, free_key, free_data, ctx) \ + { \ + .hash_fn = (hash_fn), .freeKey = (free_key).freeData = (free_data).equal_fn = (equal_fn), \ + .ctx = (ctx), .buckets = NULL, .cap = 0, .cap_bits = 0, .sz = 0, \ + } + +void hashmap__init(struct HashMap * map, + hashmap_hash_fn hash_fn, + hashmap_equal_fn equal_fn, + FreeFunc free_key, + FreeFunc free_data, + void * ctx); + + +struct HashMap * hashmap__new(hashmap_hash_fn hash_fn, + hashmap_equal_fn equal_fn, + FreeFunc free_key, + FreeFunc free_data, + void * ctx); + + +void hashmap__clear(struct HashMap * map); +void hashmap__free(struct HashMap * map); + +size_t hashmap__size(const struct HashMap * map); +size_t hashmap__capacity(const struct HashMap * map); + +/* + * Hashmap insertion strategy: + * - HASHMAP_ADD - only add key/value if key doesn't exist yet; + * - HASHMAP_SET - add key/value pair if key doesn't exist yet; otherwise, + * update value; + * - HASHMAP_UPDATE - update value, if key already exists; otherwise, do + * nothing and return -ENOENT; + * - HASHMAP_APPEND - always add key/value pair, even if key already exists. + * This turns hashmap into a multimap by allowing multiple values to be + * associated with the same key. Most useful read API for such hashmap is + * hashmap__for_each_key_entry() iteration. If hashmap__find() is still + * used, it will return last inserted key/value entry (first in a bucket + * chain). + */ +enum hashmap_insert_strategy { + HASHMAP_ADD, + HASHMAP_SET, + HASHMAP_UPDATE, + HASHMAP_APPEND, +}; + +/* + * hashmap__insert() adds key/value entry w/ various semantics, depending on + * provided strategy value. If a given key/value pair replaced already + * existing key/value pair, both old key and old value will be returned + * through old_key and old_value to allow calling code do proper memory + * management. + */ +int hashmap__insert(struct HashMap * map, + const void * key, + void * value, + enum hashmap_insert_strategy strategy, + const void ** old_key, + void ** old_value); + +static inline int hashmap__add(struct HashMap * map, const void * key, void * value) { + return hashmap__insert(map, key, value, HASHMAP_ADD, NULL, NULL); +} + +static inline int hashmap__set(struct HashMap * map, + const void * key, + void * value, + const void ** old_key, + void ** old_value) { + return hashmap__insert(map, key, value, HASHMAP_SET, old_key, old_value); +} + +static inline int hashmap__update(struct HashMap * map, + const void * key, + void * value, + const void ** old_key, + void ** old_value) { + return hashmap__insert(map, key, value, HASHMAP_UPDATE, old_key, old_value); +} + +static inline int hashmap__append(struct HashMap * map, const void * key, void * value) { + return hashmap__insert(map, key, value, HASHMAP_APPEND, NULL, NULL); +} + +bool hashmap__delete(struct HashMap * map, + const void * key, + const void ** old_key, + void ** old_value); + +bool hashmap__find(const struct HashMap * map, const void * key, void ** value); + +/* + * hashmap__for_each_entry - iterate over all entries in hashmap + * @map: hashmap to iterate + * @cur: struct hashmap_entry * used as a loop cursor + * @bkt: integer used as a bucket loop cursor + */ +#define hashmap__for_each_entry(map, cur, bkt) \ + for (bkt = 0; bkt < map->cap; bkt++) \ + for (cur = map->buckets[bkt]; cur; cur = cur->next) + +/* + * hashmap__for_each_entry_safe - iterate over all entries in hashmap, safe + * against removals + * @map: hashmap to iterate + * @cur: struct hashmap_entry * used as a loop cursor + * @tmp: struct hashmap_entry * used as a temporary next cursor storage + * @bkt: integer used as a bucket loop cursor + */ +#define hashmap__for_each_entry_safe(map, cur, tmp, bkt) \ + for (bkt = 0; bkt < map->cap; bkt++) \ + for (cur = map->buckets[bkt]; cur && ({ \ + tmp = cur->next; \ + true; \ + }); \ + cur = tmp) + +/* + * hashmap__for_each_key_entry - iterate over entries associated with given key + * @map: hashmap to iterate + * @cur: struct hashmap_entry * used as a loop cursor + * @key: key to iterate entries for + */ +#define hashmap__for_each_key_entry(map, cur, _key) \ + for (cur = ({ \ + size_t bkt = hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits); \ + map->buckets ? map->buckets[bkt] : NULL; \ + }); \ + cur; \ + cur = cur->next) \ + if (map->equal_fn(cur->key, (_key), map->ctx)) + +#define hashmap__for_each_key_entry_safe(map, cur, tmp, _key) \ + for (cur = ({ \ + size_t bkt = hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits); \ + cur = map->buckets ? map->buckets[bkt] : NULL; \ + }); \ + cur && ({ \ + tmp = cur->next; \ + true; \ + }); \ + cur = tmp) \ + if (map->equal_fn(cur->key, (_key), map->ctx)) + +#endif /* __LIBBPF_HASHMAP_H */ diff --git a/kernel/src/ds/bpf/test/hashmap_test.c b/kernel/src/ds/bpf/test/hashmap_test.c new file mode 100644 index 00000000..3334434b --- /dev/null +++ b/kernel/src/ds/bpf/test/hashmap_test.c @@ -0,0 +1,142 @@ +#include +#include +#include + + +size_t int_hash_fn(const void * key, void * ctx) { + return (size_t) * (int *)key; +} + +bool int_compare_fn(const void * key1, const void * key2, void * ctx) { + return *(int *)key1 == *(int *)key2; +} + +void fakeFree(void * fake) { + UNUSED(fake); +} + +void simpleFree(void * val) { + kfree(val); +} + +TEST_CREATE(test_create_hm, { + HashMap * hm = hashmap__new(int_hash_fn, int_compare_fn, fakeFree, fakeFree, NULL); + + int key = 5; + int data = 42; + + hashmap__add(hm, &key, &data); + + ASSERT(hashmap__find(hm, &key, NULL)); + + hashmap__free(hm); +}) + + +TEST_CREATE(test_free_entries_hm, { + HashMap * hm = hashmap__new(int_hash_fn, int_compare_fn, simpleFree, simpleFree, NULL); + + int * key = (int *)kmalloc(sizeof(int)); + int * value = (int *)kmalloc(sizeof(int)); + *key = 42; + *value = 69; + + hashmap__add(hm, key, value); + + hashmap__free(hm); + + // Test framework will assert that we won't leak. +}) + +TEST_CREATE(test_find_hm, { + HashMap * hm = hashmap__new(int_hash_fn, int_compare_fn, fakeFree, fakeFree, NULL); + + int key = 5; + int data = 42; + + hashmap__add(hm, &key, &data); + + ASSERT_EQ(hashmap__size(hm), 1); + + int * ptr = NULL; + void ** dp = (void **)&ptr; + + ASSERT(hashmap__find(hm, &key, dp)); + ASSERT_EQ(&data, *dp); + ASSERT_EQ(data, *ptr); + + hashmap__free(hm); +}) + +TEST_CREATE(test_set_hm, { + HashMap * hm = hashmap__new(int_hash_fn, int_compare_fn, fakeFree, fakeFree, NULL); + + int key = 5; + int data = 42; + + // add 42 + hashmap__add(hm, &key, &data); + + ASSERT_EQ(hashmap__size(hm), 1); + + int * ptr = NULL; + void ** dp = (void **)&ptr; + + ASSERT(hashmap__find(hm, &key, dp)); + ASSERT_EQ(&data, *dp); + ASSERT_EQ(data, *ptr); + + // set 42 to 69 + int new_data = 69; + hashmap__set(hm, &key, &new_data, NULL, NULL); + + ASSERT(hashmap__find(hm, &key, dp)); + ASSERT_EQ(&new_data, *dp); + ASSERT_EQ(new_data, *ptr); + + // set (144,196) which doesn't exist yet + int extra_data = 196; + int extra_key = 144; + hashmap__set(hm, &extra_key, &extra_data, NULL, NULL); + + ASSERT(hashmap__find(hm, &extra_key, dp)); + ASSERT_EQ(&extra_data, *dp); + ASSERT_EQ(extra_data, *ptr); + + hashmap__free(hm); +}) + + +TEST_CREATE(test_update_hm, { + HashMap * hm = hashmap__new(int_hash_fn, int_compare_fn, fakeFree, fakeFree, NULL); + + int key = 5; + int data = 42; + + // add 42 + hashmap__add(hm, &key, &data); + + ASSERT_EQ(hashmap__size(hm), 1); + + int * ptr = NULL; + void ** dp = (void **)&ptr; + + ASSERT(hashmap__find(hm, &key, dp)); + ASSERT_EQ(&data, *dp); + ASSERT_EQ(data, *ptr); + + // set 42 to 69 + int new_data = 69; + hashmap__update(hm, &key, &new_data, NULL, NULL); + + ASSERT(hashmap__find(hm, &key, dp)); + ASSERT_EQ(&new_data, *dp); + ASSERT_EQ(new_data, *ptr); + + // set (144,196) which doesn't exist + int extra_data = 196; + int extra_key = 144; + ASSERT_EQ(hashmap__update(hm, &extra_key, &extra_data, NULL, NULL), -1); + + hashmap__free(hm); +}) diff --git a/kernel/src/ds/include/ds.h b/kernel/src/ds/include/ds.h new file mode 100644 index 00000000..7f5ea369 --- /dev/null +++ b/kernel/src/ds/include/ds.h @@ -0,0 +1,17 @@ +#ifndef DS_H +#define DS_H + +#include +#include + +// used across datastructures +typedef void (*FreeFunc)(void * data); +typedef bool (*CompareFunc)(void * in, void * other); + +#include +#include +#include +#include +#include + +#endif diff --git a/kernel/include/data_structures/priority_queue.h b/kernel/src/ds/include/priority_queue.h similarity index 64% rename from kernel/include/data_structures/priority_queue.h rename to kernel/src/ds/include/priority_queue.h index 927b274a..a49ae56f 100644 --- a/kernel/include/data_structures/priority_queue.h +++ b/kernel/src/ds/include/priority_queue.h @@ -1,33 +1,33 @@ -/* - * priority_queue.h - * - * Created on: Apr 16, 2015 - * Author: mwkurian - */ - #ifndef KERNEL_INCLUDE_PRIORITY_QUEUE_H_ #define KERNEL_INCLUDE_PRIORITY_QUEUE_H_ +/* + * Priority queue implementation. + * The element with the lowest priority value will get dequeued first. + * Supports duplicate priorities. + */ + typedef struct prq_node { - int index; // FIXME double underscore + int __index; int priority; void * data; } prq_node; typedef struct prq_handle { - prq_node ** heap; - int count; - int heap_size; + prq_node ** __heap; + int __count; + int __heap_size; } prq_handle; void prq_enqueue(prq_handle * queue, prq_node * node); prq_node * prq_dequeue(prq_handle * queue); void prq_remove(prq_handle * queue, prq_node * node); -prq_handle* prq_create(); -prq_handle* prq_create_fixed(int n); +prq_handle * prq_create(); +prq_handle * prq_create_fixed(int n); void prq_free(prq_handle * queue); int prq_count(prq_handle * queue); prq_node * prq_peek(prq_handle * queue); prq_node * prq_create_node(); void prq_free_node(prq_node * node); -#endif /* KERNEL_INCLUDE_PRIORITY_QUEUE_H_ */ + +#endif diff --git a/kernel/src/ds/include/qstr.h b/kernel/src/ds/include/qstr.h new file mode 100644 index 00000000..de97edc7 --- /dev/null +++ b/kernel/src/ds/include/qstr.h @@ -0,0 +1,37 @@ +#ifndef QSTR_H +#define QSTR_H + +#include +#include + +// A Qstr or quickstring, is a string which stores it's length, +// and on first compare calculates and stores its hash to speed up +// further comparisons. Apart from storing the length, the last byte of a Qstr's +// data is always a null. Therefore a pointer to a Qstr is *always* also a valid null +// terminated string. + +typedef struct Qstr { + char * data; + size_t length; + uint32_t hash; +} Qstr; + +Qstr qstr_from_null_terminated_string(char * arr); +Qstr qstr_from_length_string(char * arr, size_t length); + +void qstr_free(Qstr * qstr); + +// Quick eq. Either compares hashes and lengths to quickly determine non equality. +// While doing full string compare, calculates the hash of left to store. If equal +// this automatically also is the hash of right and both are set. Otherwise just the +// hash of left is set. +bool qstr_eq(Qstr * left, Qstr * right); + +// Normal strincompare. Slightly slower than default compare. +// Also calculates hash of left to speed up further stringcompares. +bool qstr_eq_null_terminated(Qstr * left, char * right); + +// Hash the qstring +void qstr_hash(Qstr * q); + +#endif diff --git a/kernel/src/ds/include/u8_array_list.h b/kernel/src/ds/include/u8_array_list.h new file mode 100644 index 00000000..a949d529 --- /dev/null +++ b/kernel/src/ds/include/u8_array_list.h @@ -0,0 +1,39 @@ +#ifndef U8ARRAY_LIST_H +#define U8ARRAY_LIST_H + +#include + +typedef struct U8ArrayList { + uint32_t length; + uint32_t capacity; + uint8_t * array; +} U8ArrayList; + +U8ArrayList * u8a_create(uint32_t initial_cap); + +// Frees the list. +void u8a_free(U8ArrayList * arr); + +// Gets element of specified index; +uint8_t u8a_get(U8ArrayList * list, uint32_t index); + +// Sets element to specific data +void u8a_set(U8ArrayList * list, uint32_t index, uint8_t data); + +// Inserts data at the end of the list +uint32_t u8a_push(U8ArrayList * list, uint8_t data); + +// Returns the topmost element and removes it fromhe list. +uint8_t u8a_pop(U8ArrayList * list); + +// Truncates the list to specified size +void u8a_resize(U8ArrayList * list, uint32_t new_size); + +// appends a null terminated string of data to the end of the list. +// Does not copy the null terminator as this can be found using the array length. +uint32_t u8a_push_string(U8ArrayList * arr, char * data); + +// Creates a new u8a with the same contents as another one. +U8ArrayList * u8a_clone(U8ArrayList * arr); + +#endif // U8ARRAY_LIST_H diff --git a/kernel/src/ds/include/vp_array_list.h b/kernel/src/ds/include/vp_array_list.h new file mode 100644 index 00000000..6de9d95e --- /dev/null +++ b/kernel/src/ds/include/vp_array_list.h @@ -0,0 +1,35 @@ +#ifndef VP_ARRAYLIST_H +#define VP_ARRAYLIST_H +#include +#include + + +typedef struct VPArrayList { + uint32_t length; + uint32_t capacity; + void ** array; +} VPArrayList; + +VPArrayList * vpa_create(uint32_t initial_cap); + +// Frees the list. +void vpa_free(VPArrayList * arr, FreeFunc freef); + +// Gets element of specified index; +void * vpa_get(VPArrayList * list, uint32_t index); + +// Sets element to specific data +void vpa_set(VPArrayList * list, uint32_t index, void * data); + +// Inserts data at the end of the list +uint32_t vpa_push(VPArrayList * list, void * data); + +// Returns the topmost element and removes it fromhe list. +void * vpa_pop(VPArrayList * list); + +// Truncates the list to specified size +void vpa_resize(VPArrayList * list, uint32_t new_size, FreeFunc freeFunc); + +void * vpa_remove(VPArrayList * list, size_t index); + +#endif diff --git a/kernel/src/ds/include/vp_singly_linked_list.h b/kernel/src/ds/include/vp_singly_linked_list.h new file mode 100644 index 00000000..50bea9c8 --- /dev/null +++ b/kernel/src/ds/include/vp_singly_linked_list.h @@ -0,0 +1,45 @@ + +#ifndef VP_SINGLY_LINKED_LIST_H +#define VP_SINGLY_LINKED_LIST_H + +#include + +// TODO: Docs + +struct VPSinglyLinkedListLink { + struct VPSinglyLinkedListLink * next; + void * data; +}; + +typedef struct VPSinglyLinkedList { + struct VPSinglyLinkedListLink * head; + size_t length; +} VPSinglyLinkedList; + + +// Iterator over a SLL +typedef struct VPSinglyLinkedListLink * VPSinglyLinkedListIterator; + +VPSinglyLinkedListIterator vpslli_create(VPSinglyLinkedList * lst); +void * vpslli_next(VPSinglyLinkedListIterator * lsti); +bool vpslli_empty(VPSinglyLinkedListIterator lsti); + +VPSinglyLinkedList * vpsll_create(); +void vpsll_free(VPSinglyLinkedList * lst, FreeFunc freef); +void vpsll_push(VPSinglyLinkedList * lst, void * data); +void * vpsll_pop(VPSinglyLinkedList * lst); +// Remove the first item for which compf returns true. +void * vpsll_remove(VPSinglyLinkedList * lst, void * data, CompareFunc compf); +void * vpsll_get(VPSinglyLinkedList * lst, size_t index); + +// returns the old value to free +void * vpsll_set(VPSinglyLinkedList * lst, size_t index, void * value); + +// Returns if the compf returns true for any item in the list (compared with the value). +bool vpsll_contains(VPSinglyLinkedList * lst, void * value, CompareFunc compf); + +size_t vpsll_length(VPSinglyLinkedList * lst); + +#define VPSLL_FOREACH(lst, i) \ + for (VPSinglyLinkedListIterator i = vpslli_create(lst); !vpslli_empty(i); vpslli_next(&(i))) +#endif diff --git a/kernel/src/ds/priority_queue.c b/kernel/src/ds/priority_queue.c new file mode 100644 index 00000000..a9790c43 --- /dev/null +++ b/kernel/src/ds/priority_queue.c @@ -0,0 +1,159 @@ +#include +#include +#include +#include + +#define AMORTIZED_CONSTANT 2 +#define DEFAULT_COUNT 10 + +// Internal implementation functions +void __prq_shift_up(prq_handle * queue, int idx); +void __prq_shift_down(prq_handle * queue, int idx); + +void __prq_shift_up(prq_handle * queue, int idx) { + prq_node ** heap = queue->__heap; + prq_node *node, *parent; + while (idx > 1 && heap[idx]->priority < heap[idx / 2]->priority) { + node = heap[idx]; + parent = heap[idx / 2]; + parent->__index = idx; + node->__index = idx / 2; + heap[idx] = parent; + heap[idx / 2] = node; + idx /= 2; + } +} + +void __prq_shift_down(prq_handle * queue, int idx) { + int cidx; // index for child + prq_node ** heap = queue->__heap; + prq_node *node, *child; + for (;;) { + cidx = idx * 2; + if (cidx > queue->__count) { + break; // it has no child + } + if (cidx < queue->__count) { + if (heap[cidx]->priority > heap[cidx + 1]->priority) { ++cidx; } + } + // swap if necessary + if (heap[cidx]->priority < heap[idx]->priority) { + node = heap[cidx]; + child = heap[idx]; + node->__index = idx; + child->__index = cidx; + heap[cidx] = child; + heap[idx] = node; + idx = cidx; + } else { + break; + } + } +} + +prq_node * prq_create_node() { + return kmalloc(sizeof(prq_node)); +} + +void prq_free_node(prq_node * node) { + assert(node != NULL); + + kfree(node); +} + +prq_node * prq_peek(prq_handle * queue) { + assert(queue != NULL); + + if (queue->__count > 0) { + return queue->__heap[1]; + } + return NULL; +} + +int prq_count(prq_handle * queue) { + assert(queue != NULL); + + return queue->__count; +} + +void __prq_amortize(prq_handle * queue) { + const int new_heap_size = queue->__heap_size * AMORTIZED_CONSTANT; + queue->__heap = krealloc(queue->__heap, sizeof(prq_node *) * new_heap_size); + queue->__heap_size = new_heap_size; +} + +void prq_enqueue(prq_handle * queue, prq_node * node) { + assert(queue != NULL); + assert(node != NULL); + + prq_node ** const heap = queue->__heap; + const int index = (node->__index = queue->__count + 1); + heap[index] = node; + ++(queue->__count); + __prq_shift_up(queue, index); + if (queue->__count + 1 == queue->__heap_size) { + __prq_amortize(queue); + } +} + +void prq_remove(prq_handle * queue, prq_node * node) { + assert(queue != NULL); + assert(node != NULL); + + if (queue->__count == 0) { + return; + } + prq_node ** heap = queue->__heap; + prq_node * end = heap[queue->__count]; + int index = (end->__index = node->__index); + if (index == -1) { + return; + } + node->__index = -1; + heap[index] = end; + heap[queue->__count + 1] = 0; + --queue->__count; + // FIXME optimize later + __prq_shift_up(queue, index); + __prq_shift_down(queue, index); +} + +prq_node * prq_dequeue(prq_handle * queue) { + assert(queue != NULL); + + if (queue->__count == 0) { + return 0; + } + prq_node ** heap = queue->__heap; + prq_node * top = heap[1]; + prq_node * end = heap[queue->__count]; + end->__index = 1; + top->__index = -1; + heap[1] = end; + heap[queue->__count] = 0; + --queue->__count; + __prq_shift_down(queue, 1); + return top; +} + +prq_handle * prq_create_fixed(int n) { + assert(n >= 1); + + prq_handle * queue = kmalloc(sizeof(prq_handle)); + queue->__count = 0; + queue->__heap_size = n + 1; + queue->__heap = kmalloc(sizeof(prq_node *) * queue->__heap_size); + return queue; +} + +prq_handle * prq_create() { + return prq_create_fixed(DEFAULT_COUNT); +} + +void prq_free(prq_handle * queue) { + assert(queue != NULL); + assert(queue->__count == 0); + + kfree(queue->__heap); + kfree(queue); +} diff --git a/kernel/src/ds/qstr.c b/kernel/src/ds/qstr.c new file mode 100644 index 00000000..c91805b1 --- /dev/null +++ b/kernel/src/ds/qstr.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +Qstr qstr_from_null_terminated_string(char * arr) { + size_t length = strlen(arr); + return qstr_from_length_string(arr, length); +} + +Qstr qstr_from_length_string(char * arr, size_t length) { + char * data = kmalloc(length + 1); + memcpy(data, arr, length); + data[length] = 0; // make null terminated. + + return (Qstr){ + .data = data, + .length = length, + .hash = 0, + }; +} + +void qstr_free(Qstr * qstr) { + kfree(qstr->data); +} + +static inline bool __eq(Qstr * left, Qstr * right, bool fake) { + // Hash function from http://www.cse.yorku.ca/~oz/hash.html (djb2) + char * rightstr; + if (!fake) { + if (left->hash != 0 && right->hash != 0 && left->hash != right->hash) { return false; } + if (left->length != right->length) { return false; } + rightstr = right->data; + } else { + rightstr = (char *)right; + } + + char * leftstr = left->data; + + uint32_t hash = 5381; + + bool equal = true; + char c; + while ((c = *(leftstr++)) != '\0') { + hash = ((hash << 5u) + hash) + c; /* hash * 33 + c */ + + if (equal && c != (*rightstr++)) { equal = false; } + } + + if (hash == 0) { + hash = 42; // just has to be non-zero as to not be confused with empty hash. + } + + left->hash = hash; + if (equal && !fake) { right->hash = hash; } + + return equal; +} + +bool qstr_eq(Qstr * left, Qstr * right) { + return __eq(left, right, false); +} + +void qstr_hash(Qstr * q) { + __eq(q, (Qstr *)"", true); +} + +bool qstr_eq_null_terminated(Qstr * left, char * right) { + return __eq(left, (Qstr *)right, true); +} diff --git a/kernel/src/ds/test/priority_queue_test.c b/kernel/src/ds/test/priority_queue_test.c new file mode 100644 index 00000000..2e3a794b --- /dev/null +++ b/kernel/src/ds/test/priority_queue_test.c @@ -0,0 +1,189 @@ +#include +#include +#include + +TEST_CREATE(test_prq_1, { + prq_handle * const queue = prq_create(); + ASSERT_NOT_NULL(queue); + prq_free(queue); +}) + +TEST_CREATE(test_prq_2, { + static const int MIN_PRIORITY = 20; + static const int MAX_PRIORITY = -20; + + prq_handle * const queue = prq_create(); + + // Add reverse + for (int i = MIN_PRIORITY; i >= MAX_PRIORITY; i--) { + prq_node * const hn = prq_create_node(); + hn->priority = i; + prq_enqueue(queue, hn); + } + + // Add forward + for (int i = MAX_PRIORITY; i <= MIN_PRIORITY; i++) { + prq_node * const hn = prq_create_node(); + hn->priority = i; + prq_enqueue(queue, hn); + } + + for (int i = MAX_PRIORITY; i <= MIN_PRIORITY; i++) { + prq_node * const hn_1 = prq_dequeue(queue); + prq_node * const hn_2 = prq_dequeue(queue); + + ASSERT_EQ(hn_1->priority, i); + ASSERT_EQ(hn_2->priority, i); + + prq_free_node(hn_1); + prq_free_node(hn_2); + } + + prq_free(queue); + PASS(); +}) + +// Tests the enqueue and dequeue functions +TEST_CREATE(test_prq_3, { + prq_handle * const queue = prq_create(); + prq_node * hn; + + hn = prq_create_node(); + hn->priority = 0; + prq_enqueue(queue, hn); + + hn = prq_create_node(); + hn->priority = -2; + prq_enqueue(queue, hn); + + hn = prq_create_node(); + hn->priority = 1; + prq_enqueue(queue, hn); + + hn = prq_create_node(); + hn->priority = -10; + prq_enqueue(queue, hn); + + hn = prq_create_node(); + hn->priority = 30; + prq_enqueue(queue, hn); + + hn = prq_dequeue(queue); + ASSERT_EQ(hn->priority, -10); + prq_free_node(hn); + + hn = prq_dequeue(queue); + ASSERT_EQ(hn->priority, -2); + prq_free_node(hn); + + hn = prq_create_node(); + hn->priority = 2; + prq_enqueue(queue, hn); + + hn = prq_dequeue(queue); + ASSERT_EQ(hn->priority, 0); + prq_free_node(hn); + + prq_dequeue(queue); + + hn = prq_dequeue(queue); + ASSERT_EQ(hn->priority, 2); + prq_free_node(hn); + + hn = prq_dequeue(queue); + ASSERT_EQ(hn->priority, 30); + prq_free_node(hn); + + prq_free(queue); + PASS(); +}) + +// Testing peek function +TEST_CREATE(test_prq_4, { + prq_handle * const queue = prq_create(); + prq_node * hn; + + ASSERT_NULL(prq_peek(queue)); + ASSERT_EQ(prq_count(queue), 0); + + hn = prq_create_node(); + hn->priority = 0; + prq_enqueue(queue, hn); + + hn = prq_create_node(); + hn->priority = 1; + prq_enqueue(queue, hn); + + hn = prq_create_node(); + hn->priority = 3; + prq_enqueue(queue, hn); + + hn = prq_dequeue(queue); + prq_free_node(hn); + + hn = prq_dequeue(queue); + prq_free_node(hn); + + hn = prq_dequeue(queue); + prq_free_node(hn); + + ASSERT_NULL(prq_peek(queue)); + ASSERT_EQ(prq_count(queue), 0); + + prq_free(queue); + PASS(); +}) + +// Test remove function +TEST_CREATE(test_prq_5, { + prq_handle * const queue_1 = prq_create(); + prq_handle * const queue_2 = prq_create(); + + prq_node * hn_1 = prq_create_node(); + hn_1->priority = 1; + + prq_node * hn_2 = prq_create_node(); + hn_2->priority = 2; + + prq_node * hn_3 = prq_create_node(); + hn_3->priority = 3; + + prq_node * hn_4 = prq_create_node(); + hn_4->priority = 4; + + prq_enqueue(queue_1, hn_1); + prq_enqueue(queue_1, hn_2); + prq_enqueue(queue_1, hn_3); + prq_enqueue(queue_1, hn_4); + prq_remove(queue_1, hn_2); + prq_remove(queue_1, hn_4); + // Double remove + prq_remove(queue_1, hn_4); + prq_enqueue(queue_2, hn_2); + prq_enqueue(queue_2, hn_4); + + ASSERT_EQ(prq_count(queue_1), 2); + ASSERT_EQ(prq_count(queue_2), 2); + + prq_node * dequeued_hn; + + dequeued_hn = prq_dequeue(queue_1); + ASSERT_EQ(dequeued_hn->priority, 1); + prq_free_node(dequeued_hn); + + dequeued_hn = prq_dequeue(queue_1); + ASSERT_EQ(dequeued_hn->priority, 3); + prq_free_node(dequeued_hn); + + dequeued_hn = prq_dequeue(queue_2); + ASSERT_EQ(dequeued_hn->priority, 2); + prq_free_node(dequeued_hn); + + dequeued_hn = prq_dequeue(queue_2); + ASSERT_EQ(dequeued_hn->priority, 4); + prq_free_node(dequeued_hn); + + prq_free(queue_1); + prq_free(queue_2); + PASS(); +}) diff --git a/kernel/src/ds/test/qstr_test.c b/kernel/src/ds/test/qstr_test.c new file mode 100644 index 00000000..a41b49a4 --- /dev/null +++ b/kernel/src/ds/test/qstr_test.c @@ -0,0 +1,87 @@ +#include +#include +#include + +TEST_CREATE(test_compare_nonequal_length, { + Qstr a = qstr_from_null_terminated_string("test"); + Qstr b = qstr_from_null_terminated_string("toast"); + ASSERT(!qstr_eq(&a, &b)); + ASSERT_EQ(a.hash, 0); + ASSERT_EQ(b.hash, 0); + qstr_free(&a); + qstr_free(&b); +}) + +TEST_CREATE(test_compare_equal_length, { + Qstr a = qstr_from_null_terminated_string("tosti"); + Qstr b = qstr_from_null_terminated_string("toast"); + ASSERT(!qstr_eq(&a, &b)); + ASSERT_NEQ(a.hash, 0); + ASSERT_EQ(b.hash, 0); + qstr_free(&a); + qstr_free(&b); +}) + +TEST_CREATE(test_compare_equal_length_eq, { + Qstr a = qstr_from_null_terminated_string("toast"); + Qstr b = qstr_from_null_terminated_string("toast"); + ASSERT(qstr_eq(&a, &b)); + ASSERT_EQ(a.hash, b.hash); + qstr_free(&a); + qstr_free(&b); +}) + +TEST_CREATE(test_compare_equal_length_eq_null, { + Qstr a = qstr_from_null_terminated_string("toast"); + ASSERT(qstr_eq_null_terminated(&a, "toast")); + ASSERT_NEQ(a.hash, 0); + + qstr_free(&a); +}) + + +TEST_CREATE(test_compare_various, { + Qstr a = qstr_from_null_terminated_string("toast"); + Qstr b = qstr_from_null_terminated_string("tosti"); + Qstr c = qstr_from_null_terminated_string("toast"); + + ASSERT(!qstr_eq(&a, &b)); + ASSERT_NEQ(a.hash, 0); + ASSERT_EQ(b.hash, 0); + + ASSERT(!qstr_eq(&b, &a)); + ASSERT_NEQ(a.hash, 0); + ASSERT_NEQ(b.hash, 0); + ASSERT_NEQ(a.hash, b.hash); + + ASSERT(qstr_eq(&c, &a)); + ASSERT(qstr_eq(&a, &c)); + ASSERT_NEQ(c.hash, 0); + + qstr_free(&a); + qstr_free(&b); + qstr_free(&c); +}) + +TEST_CREATE(test_hash, { + Qstr a = qstr_from_null_terminated_string("toast"); + Qstr b = qstr_from_null_terminated_string("toast"); + + qstr_eq(&b, &a); + + a.hash = 0; + + qstr_hash(&a); + + ASSERT_NEQ(a.hash, 0); + ASSERT_EQ(a.hash, b.hash); + + qstr_free(&a); + qstr_free(&b); + + isize_t o = 1; + isize_t n = -1; + n = abs(n); + + ASSERT_EQ(o, n); +}) diff --git a/kernel/src/ds/test/u8_array_list_test.c b/kernel/src/ds/test/u8_array_list_test.c new file mode 100644 index 00000000..33fe050d --- /dev/null +++ b/kernel/src/ds/test/u8_array_list_test.c @@ -0,0 +1,111 @@ +#include +#include + + +TEST_CREATE(u8a_push_get_pop_test, { + uint32_t length = 30; + + U8ArrayList * arr = u8a_create(1); + for (int i = 0; i < length; i++) { u8a_push(arr, i % 0xff); } + + ASSERT_EQ(arr->length, length); + ASSERT_GTEQ(arr->capacity, length); + + for (int i = 0; i < length; i++) { + uint8_t a = u8a_get(arr, i); + ASSERT_EQ(a, i % 0xff); + } + + ASSERT_EQ(arr->length, length); + ASSERT_GTEQ(arr->capacity, length); + + for (int i = length - 1; i >= 0; i--) { ASSERT_EQ(u8a_pop(arr), i % 0xff); } + + ASSERT_EQ(arr->length, 0); + ASSERT_LT(arr->capacity, length); + + u8a_free(arr); +}) + +TEST_CREATE(u8a_push_set_pop_test, { + U8ArrayList * arr = u8a_create(1); + for (int i = 0; i < 1000; i++) { u8a_push(arr, i % 0xff); } + + ASSERT_EQ(arr->length, 1000); + ASSERT_GTEQ(arr->capacity, 1000); + + for (int i = 0; i < 1000; i++) { u8a_set(arr, i, 42); } + + ASSERT_EQ(arr->length, 1000); + ASSERT_GTEQ(arr->capacity, 1000); + + for (int i = 999; i >= 0; i--) { ASSERT_EQ(u8a_pop(arr), 42); } + + ASSERT_EQ(arr->length, 0); + ASSERT_LT(arr->capacity, 1000); + + u8a_free(arr); +}) + +TEST_CREATE(u8a_resize_test, { + U8ArrayList * list = u8a_create(8); + ASSERT_EQ(list->length, 0); + ASSERT_EQ(list->capacity, 8); + + u8a_resize(list, 4); + ASSERT_EQ(list->length, 0); + ASSERT_EQ(list->capacity, 4); + + u8a_free(list); +}) + +TEST_CREATE(u8a_push_string_test, { + U8ArrayList * list = u8a_create(1); + + size_t length = u8a_push_string(list, "TESTSTRING"); + + ASSERT_EQ(length, list->length); + ASSERT_EQ(length, 10); + + ASSERT_GTEQ(list->capacity, 10); + + ASSERT_EQ(u8a_get(list, 0), (uint8_t)'T'); + ASSERT_EQ(u8a_get(list, 1), (uint8_t)'E'); + ASSERT_EQ(u8a_get(list, 2), (uint8_t)'S'); + ASSERT_EQ(u8a_get(list, 3), (uint8_t)'T'); + ASSERT_EQ(u8a_get(list, 4), (uint8_t)'S'); + ASSERT_EQ(u8a_get(list, 5), (uint8_t)'T'); + ASSERT_EQ(u8a_get(list, 6), (uint8_t)'R'); + ASSERT_EQ(u8a_get(list, 7), (uint8_t)'I'); + ASSERT_EQ(u8a_get(list, 8), (uint8_t)'N'); + ASSERT_EQ(u8a_get(list, 9), (uint8_t)'G'); + + u8a_free(list); +}) + +TEST_CREATE(u8a_clone_test, { + U8ArrayList * list = u8a_create(1); + u8a_push_string(list, "TESTSTRING"); + + U8ArrayList * list2 = u8a_clone(list); + + + ASSERT_EQ(list2->length, list->length); + ASSERT_EQ(list2->length, 10); + + ASSERT_GTEQ(list2->capacity, 10); + + ASSERT_EQ(u8a_get(list2, 0), (uint8_t)'T'); + ASSERT_EQ(u8a_get(list2, 1), (uint8_t)'E'); + ASSERT_EQ(u8a_get(list2, 2), (uint8_t)'S'); + ASSERT_EQ(u8a_get(list2, 3), (uint8_t)'T'); + ASSERT_EQ(u8a_get(list2, 4), (uint8_t)'S'); + ASSERT_EQ(u8a_get(list2, 5), (uint8_t)'T'); + ASSERT_EQ(u8a_get(list2, 6), (uint8_t)'R'); + ASSERT_EQ(u8a_get(list2, 7), (uint8_t)'I'); + ASSERT_EQ(u8a_get(list2, 8), (uint8_t)'N'); + ASSERT_EQ(u8a_get(list2, 9), (uint8_t)'G'); + + u8a_free(list); + u8a_free(list2); +}) diff --git a/kernel/src/ds/test/vp_array_list_test.c b/kernel/src/ds/test/vp_array_list_test.c new file mode 100644 index 00000000..6de9d95e --- /dev/null +++ b/kernel/src/ds/test/vp_array_list_test.c @@ -0,0 +1,35 @@ +#ifndef VP_ARRAYLIST_H +#define VP_ARRAYLIST_H +#include +#include + + +typedef struct VPArrayList { + uint32_t length; + uint32_t capacity; + void ** array; +} VPArrayList; + +VPArrayList * vpa_create(uint32_t initial_cap); + +// Frees the list. +void vpa_free(VPArrayList * arr, FreeFunc freef); + +// Gets element of specified index; +void * vpa_get(VPArrayList * list, uint32_t index); + +// Sets element to specific data +void vpa_set(VPArrayList * list, uint32_t index, void * data); + +// Inserts data at the end of the list +uint32_t vpa_push(VPArrayList * list, void * data); + +// Returns the topmost element and removes it fromhe list. +void * vpa_pop(VPArrayList * list); + +// Truncates the list to specified size +void vpa_resize(VPArrayList * list, uint32_t new_size, FreeFunc freeFunc); + +void * vpa_remove(VPArrayList * list, size_t index); + +#endif diff --git a/kernel/src/ds/test/vp_singly_linked_list_test.c b/kernel/src/ds/test/vp_singly_linked_list_test.c new file mode 100644 index 00000000..975ce70b --- /dev/null +++ b/kernel/src/ds/test/vp_singly_linked_list_test.c @@ -0,0 +1,134 @@ +#include +#include + + +TEST_CREATE(test_create_ll, { + VPSinglyLinkedList * lst = vpsll_create(); + + uint32_t num = 10; + + for (uint32_t i = 0; i < num; i++) { vpsll_push(lst, (void *)i); } + + ASSERT_EQ(vpsll_length(lst), num); + + for (int32_t i = num - 1; i >= 0; i--) { ASSERT_EQ((int32_t)vpsll_pop(lst), i); } + + vpsll_free(lst, NULL); +}) + + +TEST_CREATE(test_iter_ll, { + VPSinglyLinkedList * lst = vpsll_create(); + + uint32_t num = 10; + + for (uint32_t i = 0; i < num; i++) { vpsll_push(lst, (void *)i); } + + ASSERT_EQ(vpsll_length(lst), num); + + size_t index = num - 1; + VPSLL_FOREACH(lst, i) { + ASSERT_EQ((size_t)i->data, index--); + } + + vpsll_free(lst, NULL); +}) + +TEST_CREATE(test_get_ll, { + VPSinglyLinkedList * lst = vpsll_create(); + + uint32_t num = 10; + + for (uint32_t i = 0; i < num; i++) { vpsll_push(lst, (void *)i); } + + ASSERT_EQ(vpsll_length(lst), num); + + isize_t index = 0; + for (isize_t i = num - 1; i >= 0; i--) { ASSERT_EQ((isize_t)vpsll_get(lst, index++), i); } + + vpsll_free(lst, NULL); +}) + +#ifdef ENABLE_TESTS +bool __compareInt(void * a, void * b) { + // ^- me wishing for lambdas in C + return *(int *)a == *(int *)b; +} +#endif + +TEST_CREATE(test_contains_true, { + VPSinglyLinkedList * lst = vpsll_create(); + + int a = 3; + int b = 5; + int c = 7; + + int f = 5; + + vpsll_push(lst, &a); + vpsll_push(lst, &b); + vpsll_push(lst, &c); + + ASSERT(vpsll_contains(lst, &f, __compareInt)); + ASSERT_EQ(vpsll_length(lst), 3); + + vpsll_free(lst, NULL); +}) + +TEST_CREATE(test_contains_false, { + VPSinglyLinkedList * lst = vpsll_create(); + + int a = 3; + int b = 5; + int c = 7; + + int f = 9; + + vpsll_push(lst, &a); + vpsll_push(lst, &b); + vpsll_push(lst, &c); + + ASSERT(!vpsll_contains(lst, &f, __compareInt)); + ASSERT_EQ(vpsll_length(lst), 3); + + vpsll_free(lst, NULL); +}) + +TEST_CREATE(test_vpsll_remove, { + VPSinglyLinkedList * lst = vpsll_create(); + + int a = 3; + int b = 5; + int c = 7; + + int f = 5; + + vpsll_push(lst, &a); + vpsll_push(lst, &b); + vpsll_push(lst, &c); + + ASSERT_EQ(vpsll_remove(lst, &f, __compareInt), &b); + ASSERT_EQ(vpsll_length(lst), 2); + + vpsll_free(lst, NULL); +}) + +TEST_CREATE(test_vpsll_set, { + VPSinglyLinkedList * lst = vpsll_create(); + + int a = 3; + int b = 5; + int c = 7; + + int f = 5; + + vpsll_push(lst, &a); + vpsll_push(lst, &b); + vpsll_push(lst, &c); + + vpsll_set(lst, 1, &f); + ASSERT_EQ(vpsll_get(lst, 1), &f); + ASSERT_EQ(vpsll_length(lst), 3); + + vpsll_free(lst, NULL); +}) diff --git a/kernel/src/ds/u8_array_list.c b/kernel/src/ds/u8_array_list.c new file mode 100644 index 00000000..d6845399 --- /dev/null +++ b/kernel/src/ds/u8_array_list.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include + +U8ArrayList * u8a_create(uint32_t initial_cap) { + U8ArrayList * list = kmalloc(sizeof(U8ArrayList)); + + *list = (U8ArrayList){ + .length = 0, .capacity = initial_cap, .array = kmalloc(initial_cap * sizeof(uint8_t))}; + + return list; +} + +void u8a_free(U8ArrayList * arr) { + if (arr->capacity > 0) { kfree(arr->array); } + kfree(arr); +} + +uint8_t u8a_get(U8ArrayList * list, uint32_t index) { + return list->array[index]; +} + +// Sets element to specific data +void u8a_set(U8ArrayList * list, uint32_t index, uint8_t data) { + list->array[index] = data; +} + +// Inserts data at the end of the list. Returns the new size. +uint32_t u8a_push(U8ArrayList * list, uint8_t data) { + if (list->capacity == 0 || list->length >= list->capacity - 1) { + uint32_t new_size = max((list->capacity + (list->capacity >> 2u)), list->capacity + 2); + + assert(new_size > list->capacity) + + list->capacity = new_size; + + list->array = krealloc(list->array, list->capacity * sizeof(uint8_t)); + } + + list->array[list->length++] = data; + + return list->length; +} + +uint32_t u8a_push_string(U8ArrayList * arr, char * data) { + size_t length = strlen(data); + + u8a_resize(arr, arr->length + length); + + for (int i = 0; i < length; i++) { arr->array[arr->length++] = data[i]; } + + return arr->length; +} + +uint8_t u8a_pop(U8ArrayList * list) { + if (list->length == 0) { return 0; } + + uint8_t res = list->array[--list->length]; + + if (list->length < (list->capacity / 2)) { + list->capacity /= 2; + list->array = krealloc(list->array, list->capacity * sizeof(uint8_t)); + } + + return res; +} + +// Resizes the list to specified size +void u8a_resize(U8ArrayList * list, uint32_t new_size) { + list->array = krealloc(list->array, new_size); + + list->capacity = new_size; + if (list->length > list->capacity) { list->length = list->capacity; } +} + +U8ArrayList * u8a_clone(U8ArrayList * arr) { + U8ArrayList * newarr = u8a_create(arr->length); + + for (int i = 0; i < arr->length; i++) { newarr->array[newarr->length++] = arr->array[i]; } + + return newarr; +} diff --git a/kernel/src/ds/vp_array_list.c b/kernel/src/ds/vp_array_list.c new file mode 100644 index 00000000..e15e3a13 --- /dev/null +++ b/kernel/src/ds/vp_array_list.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include + +struct VPArrayList * vpa_create(uint32_t initial_cap) { + VPArrayList * list = kmalloc(sizeof(VPArrayList)); + *list = (VPArrayList){ + .length = 0, .capacity = initial_cap, .array = kmalloc(initial_cap * sizeof(void *))}; + + return list; +} + +void vpa_free(VPArrayList * arr, FreeFunc freefunc) { + if (freefunc != NULL) { + for (uint32_t i = 0; i < arr->length; i++) { freefunc(arr->array[i]); } + } + + kfree(arr->array); + kfree(arr); +} + +void * vpa_get(VPArrayList * list, uint32_t index) { + return list->array[index]; +} + +// Sets element to specific data +void vpa_set(VPArrayList * list, uint32_t index, void * data) { + list->array[index] = data; +} + +// Inserts data at the end of the list. Returns the new size. +uint32_t vpa_push(VPArrayList * list, void * data) { + list->array[list->length++] = data; + + if (list->length >= list->capacity) { + uint32_t new_size = max((list->capacity + (list->capacity >> 2u)), list->capacity + 2); + + assert(new_size > list->capacity) + + list->capacity = new_size; + + list->array = krealloc(list->array, list->capacity * sizeof(void *)); + } + + return list->length; +} + +void * vpa_pop(VPArrayList * list) { + if (list->length == 0) { return 0; } + + void * res = list->array[--list->length]; + + if (list->length < (list->capacity / 2)) { + list->capacity /= 2; + list->array = krealloc(list->array, list->capacity * sizeof(void *)); + } + + return res; +} + +// Resizes the list to specified size +void vpa_resize(VPArrayList * list, uint32_t new_size, FreeFunc freeFunc) { + list->capacity = new_size; + + if (list->length > list->capacity) { + if (freeFunc != NULL) { + for (uint32_t i = list->length; i > list->capacity; i--) { freeFunc(list->array[i]); } + } + + list->length = list->capacity; + } + + list->array = krealloc(list->array, new_size); +} + +void * vpa_remove(VPArrayList * list, size_t index); diff --git a/kernel/src/ds/vp_singly_linked_list.c b/kernel/src/ds/vp_singly_linked_list.c new file mode 100644 index 00000000..9f78cb5d --- /dev/null +++ b/kernel/src/ds/vp_singly_linked_list.c @@ -0,0 +1,117 @@ +#include +#include +#include + +VPSinglyLinkedList * vpsll_create() { + VPSinglyLinkedList * res = kmalloc(sizeof(VPSinglyLinkedList)); + res->head = NULL; + res->length = 0; + return res; +} + + +void vpsll_free(VPSinglyLinkedList * lst, FreeFunc freef) { + struct VPSinglyLinkedListLink * curr = lst->head; + while (curr != NULL) { + struct VPSinglyLinkedListLink * last = curr; + curr = curr->next; + if (freef != NULL) { freef(last->data); } + kfree(last); + } + kfree(lst); +} + +void vpsll_push(VPSinglyLinkedList * lst, void * data) { + struct VPSinglyLinkedListLink * node = kmalloc(sizeof(struct VPSinglyLinkedListLink)); + node->data = data; + + node->next = lst->head; + lst->head = node; + + lst->length++; +} + +void * vpsll_pop(VPSinglyLinkedList * lst) { + struct VPSinglyLinkedListLink * oldhead = lst->head; + void * contents = oldhead->data; + + lst->head = oldhead->next; + kfree(oldhead); + + lst->length--; + + return contents; +} + + +// Remove the first item for which compf returns true. +void * vpsll_remove(VPSinglyLinkedList * lst, void * data, CompareFunc compf) { + struct VPSinglyLinkedListLink * prev = NULL; + VPSLL_FOREACH(lst, i) { + if (compf(i->data, data)) { + void * value = i->data; + if (prev == NULL) { + lst->head = i->next; + } else { + prev->next = i->next; + kfree(i); + } + lst->length--; + return value; + } + prev = i; + } + + return NULL; +} + +inline static struct VPSinglyLinkedListLink * __link_at_index(VPSinglyLinkedList * lst, + size_t index) { + if (index > lst->length) { return NULL; } + VPSLL_FOREACH(lst, i) { + if (index-- == 0) { return i; } + } + + return NULL; +} + +void * vpsll_get(VPSinglyLinkedList * lst, size_t index) { + return __link_at_index(lst, index)->data; +} + +// returns the old value to free +void * vpsll_set(VPSinglyLinkedList * lst, size_t index, void * value) { + struct VPSinglyLinkedListLink * link = __link_at_index(lst, index); + if (link == NULL) { return NULL; } + + void * old = link->data; + link->data = value; + + return old; +} + +// Returns if the compf returns true for any item in the list (compared with the value). +bool vpsll_contains(VPSinglyLinkedList * lst, void * value, CompareFunc compf) { + VPSLL_FOREACH(lst, i) { + if (compf(i->data, value)) { return true; } + } + return false; +} + +size_t vpsll_length(VPSinglyLinkedList * lst) { + return lst->length; +} + +VPSinglyLinkedListIterator vpslli_create(VPSinglyLinkedList * lst) { + return lst->head; +} + +void * vpslli_next(VPSinglyLinkedListIterator * lsti) { + void * nxt = (*lsti)->data; + *lsti = (*lsti)->next; + return nxt; +} + +bool vpslli_empty(VPSinglyLinkedListIterator lsti) { + return lsti == NULL; +} diff --git a/kernel/src/fs/file.c b/kernel/src/fs/file.c new file mode 100644 index 00000000..c006ee55 --- /dev/null +++ b/kernel/src/fs/file.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include + + +void create_file(Path * p, VfsErr * err) {} + +void create_dir(Vfs * vfs, Path * p, VfsErr * err) { + if (path_exists(vfs, p)) { + if (err != NULL && *err == OK) { *err = ERR_EXISTS; } + return; + } + + Path * parent = u8a_clone(p); + path_parent(parent); + + VfsErr ourErr = OK; + DirEntry * parentDir = path_get_direntry(vfs, parent, &ourErr); + + // TODO: make a macro for error handling? + if (ourErr != OK || parentDir == NULL) { + if (err != NULL && *err == OK && ourErr != OK) { + *err = ourErr; + } else if (err != NULL) { + *err = ERR_NO_PARENT; + } + return; + } + + DirEntry * child = kmalloc(sizeof(DirEntry)); + UNUSED(child); + // memcpy(child->name, ) + + // parentDir->inode->fs_identifier->operations->create_dir(parentDir, , &ourErr); +} + +// void remove_dir(Path * p, bool recurse, VfsErr * err); +// void remove_file(Path * p, VfsErr * err); +// +// VPArrayList * list_dir(Path * p, VfsErr * err); +// +// File * open_file(Path * p, VfsErr * err); +// size_t read_file(File * f, uint8_t * buf, size_t length, VfsErr * err); +// size_t write_file(File * f, uint8_t * buf, size_t length, VfsErr * err); +// void seek_file(File * f, size_t pos, VfsErr * err); +// void close_file(File * f, VfsErr * err); diff --git a/kernel/src/fs/include/file.h b/kernel/src/fs/include/file.h new file mode 100644 index 00000000..35c535ff --- /dev/null +++ b/kernel/src/fs/include/file.h @@ -0,0 +1,33 @@ + +#ifndef FILE_H +#define FILE_H + +#include +#include + +#include "path.h" + +struct FsOperations; + +typedef struct File { + struct DirEntry * dentry; + size_t file_position; + const struct FsOperations * operations; +} File; + +void create_file(Path * p, enum VfsErr * err); +void create_dir(struct Vfs * vfs, Path * p, enum VfsErr * err); + +void remove_dir(Path * p, bool recurse, enum VfsErr * err); +void remove_file(Path * p, enum VfsErr * err); + +VPArrayList * list_dir(Path * p, enum VfsErr * err); + +File * open_file(Path * p, enum VfsErr * err); +size_t read_file(File * f, uint8_t * buf, size_t length, enum VfsErr * err); +size_t write_file(File * f, uint8_t * buf, size_t length, enum VfsErr * err); +void seek_file(File * f, size_t pos, enum VfsErr * err); +void close_file(File * f, enum VfsErr * err); + + +#endif diff --git a/kernel/src/fs/include/fs.h b/kernel/src/fs/include/fs.h new file mode 100644 index 00000000..c509529d --- /dev/null +++ b/kernel/src/fs/include/fs.h @@ -0,0 +1,13 @@ + +#ifndef FS_H +#define FS_H + +struct Vfs; +enum VfsErr; + +#include +#include +#include +#include + +#endif diff --git a/kernel/src/fs/include/inode.h b/kernel/src/fs/include/inode.h new file mode 100644 index 00000000..d3628039 --- /dev/null +++ b/kernel/src/fs/include/inode.h @@ -0,0 +1,45 @@ + +#ifndef INODE_H +#define INODE_H + +#include +#include +#include +#include + + +typedef enum { + DIRECTORY, + FILE, +} InodeType; + +// This is the base Inode. Any filesystem can extend it for it's own needs. +// The first field in any extended Inode must be this Inode. This makes +// casting between extended inodes and base inodes seamless as long as you +// refer to inodes only by it's pointer. +typedef struct Inode { + InodeType inode_type; + uint32_t id; + uint32_t refcount; + const struct FsIdentifier * fs_identifier; + struct DirEntry * direntry; + struct Inode * next; + bool should_delete; + struct Vfs * vfs; +} Inode; + +typedef struct DirEntry { + struct Inode * inode; + Qstr name; + struct DirEntry * parent; +} DirEntry; + +Inode create_inode_base(struct Vfs * vfs, + InodeType type, + const struct FsIdentifier * fs, + DirEntry * dirEntry); + +DirEntry * create_direntry(Qstr name, DirEntry * parent); +void free_direntry(DirEntry * d); + +#endif diff --git a/kernel/src/fs/include/path.h b/kernel/src/fs/include/path.h new file mode 100644 index 00000000..eb8a5555 --- /dev/null +++ b/kernel/src/fs/include/path.h @@ -0,0 +1,99 @@ + +#ifndef PATH_H +#define PATH_H + +#include +#include +#include + +struct Vfs; +enum VfsErr; + +typedef U8ArrayList Path; + +const Path ROOT_PATH; + +// Parse the path and return the direntry which corresponds with the path. +struct DirEntry * path_get_direntry(struct Vfs * vfs, Path * path, enum VfsErr * err); + +// Duplicates a path. +Path * path_clone(Path * path); + +// Creates a new path from a string. +Path * path_from_string(char * str); + +// Appends a string to the end of a path. +// Inserts a slash ('/') between the path and the new element. +void path_append(Path * path, char * elem); + +// Returns the path without it's last element. +// If the path is absolute and there is only one element in the path, +// or the path is root ('/'), returns '/'. +// +// If the path is relative and there's only one element in the path, +// or the path is the current directory ('.'), returns '.' +// +// If the path is empty, returns root. +// +// Examples: +// '.' => '.' +// '' => '/' +// './test' => '.' +// '.test' => '.' +// 'test' => '.' +// '/test' => '/' +// '/a/b/c' => '/a/b' +// './a/b' => './a' +void path_parent(Path * path); + +// Frees a path completely +void path_free(Path * path); + +// Returns true if the path starts with '/' +bool path_is_absolute(Path * path); +// Inverse of `path_is_absolute` +bool path_is_relative(Path * path); +// Returns the final component of a path. +void path_filename(Path * path); +// The same as [path_filename] but copies the path. +Path * path_filename_cloned(Path * path); + +// Returns the part of the filename before the extension. +// examples: +// ".test" ==> .test +// "test.txt" ==> test +// "test" ==> test +// "" ==> NULL (no filename) +char * path_filestem(Path * path); + +// Returns the part of the filename after the stem. +// examples: +// ".test" ==> NULL +// "test.txt" ==> txt +// "test" ==> NULL +// "" ==> NULL (no filename) +char * path_extension(Path * path); + + +// Joins two paths together. +// After a join, the first path (`base`) is extended with the second path +// and the econd path is freed. +void path_join(Path base, Path * path); + +// Produces a string representation of the path. The string should be freed. +// The path that is converted into the string is freed by this function. +char * path_into_string(Path * path); + +// Test if the paths are exactly equal. +bool path_contents_equal(Path * a, Path * b); + +// Tests if the paths point to the same file. (slower) +bool path_parsed_equal(Path * a, Path * b); + +// Prints a path. +void path_print(Path * path); + +// Checks if a path has an associated DirEntry +bool path_exists(struct Vfs * vfs, Path * path); + +#endif diff --git a/kernel/src/fs/include/vfs.h b/kernel/src/fs/include/vfs.h new file mode 100644 index 00000000..2f8a73df --- /dev/null +++ b/kernel/src/fs/include/vfs.h @@ -0,0 +1,75 @@ +#ifndef VFS_H +#define VFS_H + +#include +#include +#include + +struct InodeOperations; +struct inode; + +typedef struct FsOperations { + /// Inode ops + // allocates a new Inode and returns this newly made Inode. + struct Inode * (*create_file)(struct DirEntry * parent, + struct DirEntry * child, + enum VfsErr * err); + struct Inode * (*create_dir)(struct DirEntry * parent, + struct DirEntry * child, + enum VfsErr * err); + void (*remove_dir)(struct DirEntry * entry, enum VfsErr * err); + VPArrayList * (*list_dir)(struct DirEntry * entry, enum VfsErr * err); + void (*move)(struct Inode * oldDir, + struct DirEntry * oldDirEntry, + struct Inode * newDir, + struct DirEntry * newDirEntry, + enum VfsErr * err); + void (*remove_file)(struct DirEntry * entry, enum VfsErr * err); + + void (*free_inode)(struct Inode * inode); + + + /// File ops + File * (*open)(struct Inode * inode, enum VfsErr * err); + size_t (*read)(File * fp, uint8_t * buf, size_t count, enum VfsErr * err); + size_t (*write)(File * fp, uint8_t * buf, size_t count, enum VfsErr * err); + void (*close)(File * fp, enum VfsErr * err); + +} FsOperations; + +typedef struct FsIdentifier { + char * fsname; + const FsOperations * operations; +} FsIdentifier; + +typedef struct Vfs { + uint32_t filesystems_size; + uint32_t filesystems_filled; + const FsIdentifier ** filesystems; // TODO: change to vpa? + + // Inodes start at the head and are added at the tail end. + // The linked list starts at head. + struct Inode * head; + struct Inode * tail; +} Vfs; + +typedef enum VfsErr { + OK, + ERR_NOT_DIR, + ERR_EXISTS, + ERR_ALLOC_FAILED, + ERR_NO_PARENT, +} VfsErr; + +// Create and returns a VFS instance +Vfs * vfs_create(); +// Adds an inode to the internal vfs inode list +VfsErr vfs_add_inode(Vfs * vfs, struct Inode * node); +// Register a new filesystem against the vfs +VfsErr vfs_register(Vfs * vfs, const FsIdentifier * fs_identifier); +// Frees all vfs related constructs: inodes,dentries, etc. +void vfs_free(Vfs * vfs); +// Get the direntry for the root of the filesystem: '/' +struct DirEntry * vfs_get_root(Vfs * vfs); + +#endif diff --git a/kernel/src/fs/inode.c b/kernel/src/fs/inode.c new file mode 100644 index 00000000..1673a06a --- /dev/null +++ b/kernel/src/fs/inode.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +uint32_t cnt = 0; + +Inode create_inode_base(Vfs * vfs, + InodeType type, + const struct FsIdentifier * fs, + DirEntry * dirEntry) { + return (Inode){ + .refcount = 0, + .id = ++cnt, + .inode_type = type, + .fs_identifier = fs, + .direntry = dirEntry, + .next = NULL, + .should_delete = false, + .vfs = vfs, + }; +} + + +DirEntry * create_direntry(Qstr name, DirEntry * parent) { + DirEntry * entry = kmalloc(sizeof(DirEntry)); + + entry->parent = parent; + entry->name = name; + + return entry; +} + +void free_direntry(DirEntry * entry) { + qstr_free(&entry->name); + kfree(entry); +} diff --git a/kernel/src/fs/path.c b/kernel/src/fs/path.c new file mode 100644 index 00000000..d634a43f --- /dev/null +++ b/kernel/src/fs/path.c @@ -0,0 +1,200 @@ + +#include +#include +#include +#include +#include +#include + + +const Path root = { + .length = 1, + .capacity = 1, + .array = (uint8_t[]){(uint8_t)'/'}, +}; + +struct DirEntry * path_get_direntry(struct Vfs * vfs, Path * path, enum VfsErr * err) { + /* + Algorithm: + ``` + // find in hashmap + + current: inode = if is_absolute(path) { + root_inode + } else { + process cwd + } + + for each part in path { + if part in inode.list_dir() { + current = inode.child(part) + } else { + return NULL + } + } + + // store in hashmap + + return curr + + ``` + */ + DirEntry * curr; + uint8_t * pathpointer; + uint8_t * endpointer = path->array + path->length; + + if (path_is_absolute(path)) { + curr = vfs_get_root(vfs); + + // + 1 because we skip the starting '/' + pathpointer = path->array + 1; + + } else { + FATAL("Inode lookup only supports absolute path right now."); + curr = NULL; + pathpointer = path->array; + } + + + while (true) { + uint8_t * nextslash = pathpointer; + for (; *nextslash != '/' && nextslash < endpointer; nextslash++) + ; + + // FIXME: `curr` may be NULL + VPArrayList * dirlist = curr->inode->fs_identifier->operations->list_dir(curr, err); + if (*err != OK) { + // Error! + return NULL; + } + + bool changed = false; + for (int i = 0; i < dirlist->length; i++) { + DirEntry * child = vpa_get(dirlist, i); + // Todo: quick cmp + if (strncmp(child->name.data, (char *)pathpointer, (nextslash - pathpointer)) == 0) { + curr = child; + changed = true; + break; + } + } + + if (!changed) { + // The path could not be found + return NULL; + } + + // Skip the slash + pathpointer = nextslash + 1; + + if (nextslash == endpointer) { return curr; } + } +} + +Path * path_clone(Path * path) { + return u8a_clone(path); +} + +Path * path_from_string(char * str) { + U8ArrayList * arr = u8a_create(1); + u8a_push_string(arr, str); + + return arr; +} + +void path_append(Path * path, char * elem) { + u8a_push(path, '/'); + u8a_push_string(path, elem); +} + +void path_parent(Path * path) { + // for the case of path='.' + if (path->length == 1 && path->array[0] == '.') { return; } + + // for the case of path='' + if (path->length == 0) { + u8a_push(path, (uint8_t)'.'); + return; + } + + for (isize_t i = path->length; i >= 0; i--) { + if (path->array[i] == '/') { + if (i == 0) { + // If we got to the start, but there's a '/' there, make the path just this '/' + path->length = 1; + } else { + // if we go back and see a /, just make this the new length. + path->length = i; + } + return; + } + } + + path->length = 0; + u8a_push(path, '.'); +} + +void path_free(Path * path) { + u8a_free(path); +} + +bool path_contents_equal(Path * a, Path * b) { + if (a->length != b->length) { return false; } + + for (int i = 0; i < a->length; i++) { + if (a->array[i] != b->array[i]) { return false; } + } + + return true; +} + +void path_print(Path * path) { + kprintf("Path: (%i) \"", path->length); + for (int i = 0; i < path->length; i++) { kprintf("%c", path->array[i]); } + kprintf("\"\n"); +} + +bool path_is_absolute(Path * path) { + return path->array[0] == (uint8_t)'/'; +} + +bool path_is_relative(Path * path) { + return !path_is_absolute(path); +} + +bool path_exists(struct Vfs * vfs, Path * path) { + DirEntry * pd = path_get_direntry(vfs, path, NULL); + return pd != NULL; +} + +void strip_chars_from_end(Path * p) { + while (u8a_get(p, p->length - 1) == '.' || u8a_get(p, p->length - 1) == '/') { u8a_pop(p); } +} + +void path_filename(Path * p) { + // partially based on Rust's file_name + + // if path ends on ".." return None + if (p->length >= 2 && p->array[p->length - 1] == '.' && p->array[p->length - 2] == '.') { + u8a_resize(p, 0); + return; + } + + // strip characters from the back + while (u8a_get(p, p->length - 1) == '.' || u8a_get(p, p->length - 1) == '/') { p->length--; } + + // Find first '/' from the back + isize_t filename_start = p->length - 1; + while (u8a_get(p, filename_start) != '/' && filename_start > -1) { --filename_start; } + filename_start++; + + size_t filename_length = p->length - filename_start; + memmove(p->array, p->array + filename_start, filename_length); + u8a_resize(p, filename_length); +} + +Path * path_filename_cloned(Path * path) { + Path * p = u8a_clone(path); + path_filename(p); + return p; +} diff --git a/kernel/src/fs/test/test.c b/kernel/src/fs/test/test.c new file mode 100644 index 00000000..ffda83ea --- /dev/null +++ b/kernel/src/fs/test/test.c @@ -0,0 +1,21 @@ +#include +#include +#include + +TEST_CREATE(test_create_vfs, { + Vfs * test_vfs = vfs_create(); + ASSERT_NOT_NULL(test_vfs); + vfs_free(test_vfs); +}) + + +TEST_CREATE(test_get_root, { + Vfs * test_vfs = vfs_create(); + tmpfs_init(test_vfs); + + Inode * root1 = (Inode *)create_tmpfs_root(test_vfs); + Inode * root2 = vfs_get_root(test_vfs)->inode; + + ASSERT_EQ(root1->id, root2->id); + vfs_free(test_vfs); +}) diff --git a/kernel/src/fs/test/test_path.c b/kernel/src/fs/test/test_path.c new file mode 100644 index 00000000..5ca24dc3 --- /dev/null +++ b/kernel/src/fs/test/test_path.c @@ -0,0 +1,244 @@ +#include +#include +#include +#include +#include + +TEST_CREATE(path_create_test, { + Path * p = path_from_string("test"); + + ASSERT_EQ(p->length, 4); + ASSERT_EQ(u8a_get(p, 0), 't'); + ASSERT_EQ(u8a_get(p, 1), 'e'); + ASSERT_EQ(u8a_get(p, 2), 's'); + ASSERT_EQ(u8a_get(p, 3), 't'); + + path_free(p); +}) + +TEST_CREATE(path_equal_test_1, { + Path * p1 = path_from_string("/a/b"); + Path * p2 = path_from_string("/a/b"); + Path * p3 = path_from_string("/a/b/c"); + + ASSERT(path_contents_equal(p1, p2)); + ASSERT(!path_contents_equal(p1, p3)); + + path_free(p1); + path_free(p2); + path_free(p3); +}) + +TEST_CREATE(path_parent_test_1, { + Path * p1 = path_from_string("/a/b/c"); + Path * p2 = path_from_string("/a/b"); + + path_parent(p1); + + ASSERT(path_contents_equal(p1, p2)); + path_free(p1); + path_free(p2); +}) + +TEST_CREATE(path_parent_test_2, { + Path * p1 = path_from_string("./a/b"); + Path * p2 = path_from_string("./a"); + + path_parent(p1); + + ASSERT(path_contents_equal(p1, p2)); + path_free(p1); + path_free(p2); +}) + +TEST_CREATE(path_parent_test_3, { + Path * p1 = path_from_string("."); + Path * p2 = path_from_string("."); + + path_parent(p1); + + ASSERT(path_contents_equal(p1, p2)); + path_free(p1); + path_free(p2); +}) + +TEST_CREATE(path_parent_test_4, { + Path * p1 = path_from_string(""); + Path * p2 = path_from_string("."); + + path_parent(p1); + + ASSERT(path_contents_equal(p1, p2)); + path_free(p1); + path_free(p2); +}) + +TEST_CREATE(path_parent_test_5, { + Path * p1 = path_from_string(""); + Path * p2 = path_from_string("."); + + path_parent(p1); + + ASSERT(path_contents_equal(p1, p2)); + path_free(p1); + path_free(p2); +}) + +TEST_CREATE(path_parent_test_6, { + Path * p1 = path_from_string("./test"); + Path * p2 = path_from_string("."); + + path_parent(p1); + + ASSERT(path_contents_equal(p1, p2)); + path_free(p1); + path_free(p2); +}) + +TEST_CREATE(path_parent_test_7, { + Path * p1 = path_from_string(".test"); + Path * p2 = path_from_string("."); + + path_parent(p1); + + ASSERT(path_contents_equal(p1, p2)); + path_free(p1); + path_free(p2); +}) + +TEST_CREATE(path_parent_test_8, { + Path * p1 = path_from_string("test"); + Path * p2 = path_from_string("."); + + path_parent(p1); + + ASSERT(path_contents_equal(p1, p2)); + path_free(p1); + path_free(p2); +}) + +TEST_CREATE(path_parent_test_9, { + Path * p1 = path_from_string("test"); + Path * p2 = path_from_string("."); + + path_parent(p1); + + ASSERT(path_contents_equal(p1, p2)); + path_free(p1); + path_free(p2); +}) + +TEST_CREATE(path_parent_test_10, { + Path * p1 = path_from_string("/test"); + Path * p2 = path_from_string("/"); + + path_parent(p1); + + ASSERT(path_contents_equal(p1, p2)); + path_free(p1); + path_free(p2); +}) + +TEST_CREATE(path_is_absolute_test, { + Path * p1 = path_from_string("/test"); + + ASSERT(path_is_absolute(p1)); + path_free(p1); +}) + +TEST_CREATE(path_is_relative_test_1, { + Path * p1 = path_from_string("./test"); + + ASSERT(path_is_relative(p1)); + path_free(p1); +}) + +TEST_CREATE(path_is_relative_test_2, { + Path * p1 = path_from_string("test"); + + ASSERT(path_is_relative(p1)); + path_free(p1); +}) + +TEST_CREATE(path_clone_test, { + Path * p1 = path_from_string("/test"); + Path * p2 = path_clone(p1); + + ASSERT(path_contents_equal(p1, p2)); + + path_free(p1); + path_free(p2); +}) + +TEST_CREATE(path_find_file_test, { + Vfs * test_vfs = vfs_create(); + tmpfs_init(test_vfs); + + create_tmpfs_root(test_vfs); + + DirEntry * root = vfs_get_root(test_vfs); + + DirEntry * newfile = create_direntry(qstr_from_null_terminated_string("test"), root); + + VfsErr err = OK; + root->inode->fs_identifier->operations->create_file(root, newfile, &err); + ASSERT_EQ(err, OK); + Path * p = path_from_string("/test"); + + DirEntry * d = path_get_direntry(test_vfs, p, &err); + ASSERT_EQ(err, OK); + + + ASSERT(qstr_eq_null_terminated(&d->name, "test")); + + path_free(p); + vfs_free(test_vfs); +}) + +TEST_CREATE(path_filename_test, { + Path * p = path_from_string("/test/test.txt"); + path_filename(p); + + + ASSERT_EQ(strncmp((char *)p->array, "test.txt", p->length), 0); + path_free(p); +}) + +TEST_CREATE(path_filename_test_trailing, { + Path * p = path_from_string("/test/test/"); + path_filename(p); + + + ASSERT_EQ(strncmp((char *)p->array, "test", p->length), 0); + path_free(p); +}) + +TEST_CREATE(path_filename_test_1, { + Path * p = path_from_string("../test/test/."); + path_filename(p); + + ASSERT_EQ(strncmp((char *)p->array, "test", p->length), 0); + path_free(p); +}) + +TEST_CREATE(path_filename_test_2, { + Path * p = path_from_string("foo.txt/.//"); + path_filename(p); + + ASSERT_EQ(strncmp((char *)p->array, "foo.txt", p->length), 0); + path_free(p); +}) + +TEST_CREATE(path_filename_test_3, { + Path * p = path_from_string("/"); + path_filename(p); + ASSERT_EQ(p->length, 0); + path_free(p); +}) + +TEST_CREATE(path_filename_test_4, { + Path * p = path_from_string("asd/.."); + path_filename(p); + ASSERT_EQ(p->length, 0); + path_free(p); +}) diff --git a/kernel/src/fs/tmpfs/include/tmpfs.h b/kernel/src/fs/tmpfs/include/tmpfs.h new file mode 100644 index 00000000..4b993347 --- /dev/null +++ b/kernel/src/fs/tmpfs/include/tmpfs.h @@ -0,0 +1,30 @@ + +#ifndef TMPFS_H +#define TMPFS_H + +#include +#include +#include +#include + +const static int TMPFS_DEFAULT_FILE_ALLOC_SIZE = 16; +const static int TMPFS_DEFAULT_DIR_ALLOC_SIZE = 4; + +typedef struct { + Inode base; + + union { + U8ArrayList * filedata; // if it's a file + VPArrayList * direntries; // if it's a directory + } data; +} TmpfsInode; + +// Initializes tmpfs and registers it to the vfs +VfsErr tmpfs_init(Vfs * vfs); + +// Creates a tmpfs root dir on the vfs; +TmpfsInode * create_tmpfs_root(Vfs * vfs); + +const FsOperations tmpfs_inode_ops; +const struct FsIdentifier * FS_TMPFS; +#endif diff --git a/kernel/src/fs/tmpfs/test/test.c b/kernel/src/fs/tmpfs/test/test.c new file mode 100644 index 00000000..e37907e5 --- /dev/null +++ b/kernel/src/fs/tmpfs/test/test.c @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include + +TEST_CREATE(test_create_file, { + Vfs * test_vfs = vfs_create(); + tmpfs_init(test_vfs); + + TmpfsInode * root = (TmpfsInode *)create_tmpfs_root(test_vfs); // PARTIAL + ASSERT_EQ(root->base.inode_type, DIRECTORY); + + DirEntry * newfile = + create_direntry(qstr_from_null_terminated_string("test"), root->base.direntry); + + + VfsErr err = OK; + root->base.fs_identifier->operations->create_file(root->base.direntry, newfile, &err); + ASSERT_EQ(err, OK); + + + ASSERT_EQ(root->data.direntries->array[0], newfile); + ASSERT_EQ(newfile->inode->inode_type, FILE); + + vfs_free(test_vfs); +}) + +TEST_CREATE(test_create_dir, { + Vfs * test_vfs = vfs_create(); + tmpfs_init(test_vfs); + + TmpfsInode * root = (TmpfsInode *)create_tmpfs_root(test_vfs); + ASSERT_EQ(root->base.inode_type, DIRECTORY); + DirEntry * newdir = + create_direntry(qstr_from_null_terminated_string("test"), root->base.direntry); + + VfsErr err = OK; + root->base.fs_identifier->operations->create_dir(root->base.direntry, newdir, &err); + + ASSERT_EQ(err, OK); + ASSERT_EQ(root->data.direntries->array[0], newdir); + ASSERT_EQ(newdir->inode->inode_type, DIRECTORY); + + vfs_free(test_vfs); +}) + +TEST_CREATE(test_create_rw_file, { + Vfs * test_vfs = vfs_create(); + tmpfs_init(test_vfs); + + TmpfsInode * root = (TmpfsInode *)create_tmpfs_root(test_vfs); + ASSERT_EQ(root->base.inode_type, DIRECTORY); + DirEntry * newfile = + create_direntry(qstr_from_null_terminated_string("test"), root->base.direntry); + + VfsErr err = OK; + root->base.fs_identifier->operations->create_file(root->base.direntry, newfile, &err); + + ASSERT_EQ(err, OK); + ASSERT_EQ(root->data.direntries->array[0], newfile); + ASSERT_EQ(newfile->inode->inode_type, FILE); + + File * file = newfile->inode->fs_identifier->operations->open(newfile->inode, &err); + + ASSERT_EQ(err, OK); + ASSERT_EQ(file->file_position, 0); + + char * data = "The TMPFS works!"; + size_t length = strlen(data) + 1; + size_t retlen1 = file->operations->write(file, (uint8_t *)data, length, &err); + ASSERT_EQ(err, OK); + ASSERT_EQ(length, retlen1); + + // Check if it didn't change the original string. Might be the same literal though + // So might be always-true + ASSERT_EQ(strcmp(data, "The TMPFS works!"), 0); + + // Reset the file pointer + file->file_position = 0; + + char read_data[length]; + + size_t retlen2 = file->operations->read(file, (uint8_t *)read_data, length, &err); + ASSERT_EQ(err, OK); + ASSERT_EQ(length, retlen2); + ASSERT_EQ(strcmp(read_data, "The TMPFS works!"), 0); + + // Close file + file->operations->close(file, &err); + ASSERT_EQ(err, OK); + + vfs_free(test_vfs); +}) + +TEST_CREATE(test_listdir, { + Vfs * test_vfs = vfs_create(); + tmpfs_init(test_vfs); + + create_tmpfs_root(test_vfs); + + DirEntry * root = vfs_get_root(test_vfs); + + DirEntry * newfile = create_direntry(qstr_from_null_terminated_string("test"), root); + + + VfsErr err = OK; + root->inode->fs_identifier->operations->create_file(root, newfile, &err); + ASSERT_EQ(err, OK); + VPArrayList * list = root->inode->fs_identifier->operations->list_dir(root, &err); + ASSERT_EQ(err, OK); + + DirEntry * first = vpa_get(list, 0); + + ASSERT(qstr_eq_null_terminated(&first->name, "test")); + + vfs_free(test_vfs); +}) diff --git a/kernel/src/fs/tmpfs/tmpfs.c b/kernel/src/fs/tmpfs/tmpfs.c new file mode 100644 index 00000000..9bef4d26 --- /dev/null +++ b/kernel/src/fs/tmpfs/tmpfs.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +VfsErr tmpfs_init(Vfs * vfs) { + return vfs_register(vfs, FS_TMPFS); +} + +TmpfsInode * create_tmpfs_root(Vfs * vfs) { + Qstr name = qstr_from_null_terminated_string("/"); + + DirEntry * entry = create_direntry(name, NULL); + + + Inode * root = (Inode *)kmalloc(1 * sizeof(TmpfsInode)); + + *root = create_inode_base(vfs, DIRECTORY, FS_TMPFS, entry); + + TmpfsInode * t_root = (TmpfsInode *)root; + + t_root->data.direntries = vpa_create(TMPFS_DEFAULT_DIR_ALLOC_SIZE); + + entry->inode = root; + + // Set head/tail + vfs->head = root; + vfs->tail = root; + root->next = NULL; + + return (TmpfsInode *)root; +} + +void add_entry_to_directory(DirEntry * parent, DirEntry * child, enum VfsErr * err) { + TmpfsInode * parent_inode = (TmpfsInode *)parent->inode; + + if (parent_inode->base.inode_type != DIRECTORY) { + if (err != NULL && *err == OK) { *err = ERR_NOT_DIR; } + return; + } + + vpa_push(parent_inode->data.direntries, child); + child->parent = parent; +} + +Inode * tmpfs_create_dir(DirEntry * parent, DirEntry * entry, enum VfsErr * err) { + Vfs * vfs = parent->inode->vfs; + + TmpfsInode * inode = kmalloc(1 * sizeof(TmpfsInode)); + + if (inode == NULL) { + if (*err != OK) { *err = ERR_ALLOC_FAILED; } + return NULL; + } + + *inode = (TmpfsInode){ + .base = create_inode_base(vfs, DIRECTORY, FS_TMPFS, entry), + .data.direntries = vpa_create(TMPFS_DEFAULT_DIR_ALLOC_SIZE), + }; + + entry->inode = (Inode *)inode; + + add_entry_to_directory(parent, entry, err); + if (*err != OK) { return NULL; } + + + vfs_add_inode(vfs, (Inode *)inode); + + return (Inode *)inode; +} + +Inode * tmpfs_create_file(DirEntry * parent, DirEntry * entry, enum VfsErr * err) { + Vfs * vfs = parent->inode->vfs; + + TmpfsInode * inode = kmalloc(1 * sizeof(TmpfsInode)); + + if (inode == NULL) { + if (*err != OK) { *err = ERR_ALLOC_FAILED; } + return NULL; + } + + *inode = (TmpfsInode){ + .base = create_inode_base(vfs, FILE, FS_TMPFS, entry), + .data.filedata = u8a_create(TMPFS_DEFAULT_FILE_ALLOC_SIZE), + }; + + entry->inode = (Inode *)inode; + + add_entry_to_directory(parent, entry, err); + if (*err != OK) { return NULL; } + + vfs_add_inode(vfs, (Inode *)inode); + + return (Inode *)inode; +} + +File * tmpfs_open_file(Inode * inode, enum VfsErr * err) { + File * file = (File *)kmalloc(sizeof(File)); + if (file == NULL) { + if (*err != OK) { *err = ERR_ALLOC_FAILED; } + return NULL; + } + + inode->refcount++; + file->dentry = inode->direntry; + file->operations = inode->fs_identifier->operations; + file->file_position = 0; + + return file; +} + + +void tmpfs_close_file(File * file, enum VfsErr * err) { + Inode * inode = file->dentry->inode; + --inode->refcount; + if (inode->should_delete && inode->refcount <= 0) { + inode->fs_identifier->operations->remove_file(file->dentry, err); + } + + kfree(file); +} + +size_t tmpfs_read_file(File * fp, uint8_t * buf, size_t count, enum VfsErr * err) { + TmpfsInode * inode = (TmpfsInode *)fp->dentry->inode; + U8ArrayList * array = inode->data.filedata; + + uint8_t * bpos = array->array + fp->file_position; + uint8_t * last = memcpy(buf, bpos, min(count, array->length - fp->file_position)); + + size_t numb = last - buf; + fp->file_position += numb; + + return numb; +} + + +size_t tmpfs_write_file(File * fp, uint8_t * buf, size_t count, enum VfsErr * err) { + TmpfsInode * inode = (TmpfsInode *)fp->dentry->inode; + U8ArrayList * array = inode->data.filedata; + + u8a_resize(array, array->capacity + count); + + memcpy(array->array + fp->file_position, buf, count); + fp->file_position += count; + + // Set the length of the array to be as long as what was already in it plus what we wrote to it. + array->length = fp->file_position; + + return count; +} + +void tmpfs_remove_file(DirEntry * entry, enum VfsErr * err) {} + +VPArrayList * tmpfs_list_dir(DirEntry * entry, enum VfsErr * err) { + TmpfsInode * inode = (TmpfsInode *)entry->inode; + return inode->data.direntries; +} + +void tmpfs_free_inode(Inode * inode) { + TmpfsInode * tmpfsInode = (TmpfsInode *)inode; + if (tmpfsInode->base.inode_type == FILE) { + u8a_free(tmpfsInode->data.filedata); + } else if (tmpfsInode->base.inode_type == DIRECTORY) { + vpa_free(tmpfsInode->data.direntries, NULL); + } + + kfree(tmpfsInode); +} + +const FsOperations tmpfs_fs_ops = { + .create_file = tmpfs_create_file, + .create_dir = tmpfs_create_dir, + + .remove_file = tmpfs_remove_file, + .list_dir = tmpfs_list_dir, + + .free_inode = tmpfs_free_inode, + + .open = tmpfs_open_file, + .close = tmpfs_close_file, + .read = tmpfs_read_file, + .write = tmpfs_write_file, +}; + +const FsIdentifier tmpfs_id = { + .fsname = "tmpfs", + .operations = &tmpfs_fs_ops, +}; + +const FsIdentifier * FS_TMPFS = &tmpfs_id; diff --git a/kernel/src/fs/vfs.c b/kernel/src/fs/vfs.c new file mode 100644 index 00000000..733be12d --- /dev/null +++ b/kernel/src/fs/vfs.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include + +Vfs * vfs_create() { + Vfs * res = kmalloc(1 * sizeof(Vfs)); + + res->head = NULL; + res->tail = NULL; + + res->filesystems_size = 10; + res->filesystems_filled = 0; + res->filesystems = kmalloc(res->filesystems_size * sizeof(FsIdentifier *)); + + // create_root(res); + + return res; +} + +void vfs_free(Vfs * vfs) { + Inode * curr = vfs->head; + if (vfs->head == NULL) { + // If no inode was ever made + assert(vfs->tail == NULL); + } else if (curr == vfs->tail) { + if (curr->direntry != NULL) { free_direntry(curr->direntry); } + + curr->fs_identifier->operations->free_inode(curr); + } else { + while (curr != NULL) { + if (curr->direntry != NULL) { free_direntry(curr->direntry); } + + Inode * last = curr; + curr = curr->next; + last->fs_identifier->operations->free_inode(last); + } + } + + kfree(vfs->filesystems); + kfree(vfs); +} + + +VfsErr vfs_add_inode(Vfs * vfs, Inode * inode) { + // inode is already present + if (inode->next != NULL || vfs->tail == inode) { return ERR_EXISTS; } + + vfs->tail->next = inode; + vfs->tail = inode; + + return OK; +} + +VfsErr vfs_register(Vfs * vfs, const FsIdentifier * ident) { + vfs->filesystems[vfs->filesystems_filled++] = ident; + if (vfs->filesystems_filled >= vfs->filesystems_size) { + vfs->filesystems_size *= 2; + vfs->filesystems = + krealloc(vfs->filesystems, vfs->filesystems_size * sizeof(FsIdentifier *)); + + if (vfs->filesystems == NULL) { return ERR_ALLOC_FAILED; } + } + + return OK; +} + + +DirEntry * vfs_get_root(Vfs * vfs) { + Inode * curr = vfs->head; + do { + DirEntry * direntry = curr->direntry; + + if (qstr_eq_null_terminated(&direntry->name, "/")) { return direntry; } + + curr = curr->next; + } while (curr != vfs->tail); + + return NULL; +} diff --git a/kernel/src/klibc/alloc.c b/kernel/src/klibc/alloc.c new file mode 100644 index 00000000..8904cce0 --- /dev/null +++ b/kernel/src/klibc/alloc.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include + +void kfree(void * ptr) { + deallocate((uint32_t *)ptr); +} + +void * kmalloc(uint32_t size) { + void * block = (void *)allocate(size); + return block; +} + + +// Allocates n * size portion of memory (set to 0) and returns it +void * kcalloc(size_t n, size_t size) { + uint32_t total_size = n * size; + void * block = kmalloc(total_size); + + if (block == NULL) { + return NULL; + } else { + memset(block, 0, total_size); + return block; + } +} + +uint32_t kmalloc_size(void * ptr) { + return allocation_size(ptr); +} + +// TODO: Implement in-place realloc if the next block is free. +// Resize memory pointed to by ptr to new size +void * krealloc(void * ptr, uint32_t newsize) { + if (ptr == NULL) { +#if MEM_DEBUG + TRACE("[MEM DEBUG] Realloc with nullptr"); +#endif + + return kmalloc(newsize); + } + + uint32_t oldsize = kmalloc_size(ptr); + + + if (newsize == 0) { + kfree(ptr); + return NULL; + } else if (newsize <= oldsize) { + return ptr; + } else { + void * newptr = kmalloc(newsize); + if (newptr) { + memcpy(newptr, ptr, oldsize); + kfree(ptr); + } + return newptr; + } +} diff --git a/kernel/include/bits/alltypes.h b/kernel/src/klibc/include/bits/alltypes.h similarity index 62% rename from kernel/include/bits/alltypes.h rename to kernel/src/klibc/include/bits/alltypes.h index 770cc5fe..842ea0b5 100644 --- a/kernel/include/bits/alltypes.h +++ b/kernel/src/klibc/include/bits/alltypes.h @@ -1,360 +1,404 @@ -#define _Addr int +#define _Addr int #define _Int64 long long -#define _Reg int +#define _Reg int #if defined(__NEED_va_list) && !defined(__DEFINED_va_list) typedef __builtin_va_list va_list; -#define __DEFINED_va_list + #define __DEFINED_va_list #endif #if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list) typedef __builtin_va_list __isoc_va_list; -#define __DEFINED___isoc_va_list + #define __DEFINED___isoc_va_list #endif #ifndef __cplusplus -#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t) + #if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t) typedef unsigned wchar_t; -#define __DEFINED_wchar_t -#endif + #define __DEFINED_wchar_t + #endif #endif #if defined(__NEED_wint_t) && !defined(__DEFINED_wint_t) typedef unsigned wint_t; -#define __DEFINED_wint_t + #define __DEFINED_wint_t #endif #if defined(__NEED_float_t) && !defined(__DEFINED_float_t) typedef float float_t; -#define __DEFINED_float_t + #define __DEFINED_float_t #endif #if defined(__NEED_double_t) && !defined(__DEFINED_double_t) typedef double double_t; -#define __DEFINED_double_t + #define __DEFINED_double_t #endif #if defined(__NEED_time_t) && !defined(__DEFINED_time_t) typedef long time_t; -#define __DEFINED_time_t + #define __DEFINED_time_t #endif #if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t) typedef long suseconds_t; -#define __DEFINED_suseconds_t + #define __DEFINED_suseconds_t #endif #if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t) -typedef struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; -#define __DEFINED_pthread_attr_t +typedef struct { + union { + int __i[9]; + unsigned __s[9]; + } __u; +} pthread_attr_t; + #define __DEFINED_pthread_attr_t #endif #if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t) -typedef struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t; -#define __DEFINED_pthread_mutex_t +typedef struct { + union { + int __i[6]; + void * __p[6]; + } __u; +} pthread_mutex_t; + #define __DEFINED_pthread_mutex_t #endif #if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t) -typedef struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; -#define __DEFINED_pthread_cond_t +typedef struct { + union { + int __i[12]; + void * __p[12]; + } __u; +} pthread_cond_t; + #define __DEFINED_pthread_cond_t #endif #if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t) -typedef struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; -#define __DEFINED_pthread_rwlock_t +typedef struct { + union { + int __i[8]; + void * __p[8]; + } __u; +} pthread_rwlock_t; + #define __DEFINED_pthread_rwlock_t #endif #if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t) -typedef struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; -#define __DEFINED_pthread_barrier_t +typedef struct { + union { + int __i[5]; + void * __p[5]; + } __u; +} pthread_barrier_t; + #define __DEFINED_pthread_barrier_t #endif #if defined(__NEED_size_t) && !defined(__DEFINED_size_t) typedef unsigned _Addr size_t; -#define __DEFINED_size_t + #define __DEFINED_size_t #endif #if defined(__NEED_uintptr_t) && !defined(__DEFINED_uintptr_t) typedef unsigned _Addr uintptr_t; -#define __DEFINED_uintptr_t + #define __DEFINED_uintptr_t #endif #if defined(__NEED_ptrdiff_t) && !defined(__DEFINED_ptrdiff_t) typedef _Addr ptrdiff_t; -#define __DEFINED_ptrdiff_t + #define __DEFINED_ptrdiff_t #endif #if defined(__NEED_ssize_t) && !defined(__DEFINED_ssize_t) typedef _Addr ssize_t; -#define __DEFINED_ssize_t + #define __DEFINED_ssize_t #endif #if defined(__NEED_intptr_t) && !defined(__DEFINED_intptr_t) typedef _Addr intptr_t; -#define __DEFINED_intptr_t + #define __DEFINED_intptr_t #endif #if defined(__NEED_regoff_t) && !defined(__DEFINED_regoff_t) typedef _Addr regoff_t; -#define __DEFINED_regoff_t + #define __DEFINED_regoff_t #endif #if defined(__NEED_register_t) && !defined(__DEFINED_register_t) typedef _Reg register_t; -#define __DEFINED_register_t + #define __DEFINED_register_t #endif #if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t) -typedef signed char int8_t; -#define __DEFINED_int8_t +typedef signed char int8_t; + #define __DEFINED_int8_t #endif #if defined(__NEED_int16_t) && !defined(__DEFINED_int16_t) -typedef short int16_t; -#define __DEFINED_int16_t +typedef short int16_t; + #define __DEFINED_int16_t #endif #if defined(__NEED_int32_t) && !defined(__DEFINED_int32_t) -typedef int int32_t; -#define __DEFINED_int32_t +typedef int int32_t; + #define __DEFINED_int32_t #endif #if defined(__NEED_int64_t) && !defined(__DEFINED_int64_t) -typedef _Int64 int64_t; -#define __DEFINED_int64_t +typedef _Int64 int64_t; + #define __DEFINED_int64_t #endif #if defined(__NEED_intmax_t) && !defined(__DEFINED_intmax_t) -typedef _Int64 intmax_t; -#define __DEFINED_intmax_t +typedef _Int64 intmax_t; + #define __DEFINED_intmax_t #endif #if defined(__NEED_uint8_t) && !defined(__DEFINED_uint8_t) -typedef unsigned char uint8_t; -#define __DEFINED_uint8_t +typedef unsigned char uint8_t; + #define __DEFINED_uint8_t #endif #if defined(__NEED_uint16_t) && !defined(__DEFINED_uint16_t) -typedef unsigned short uint16_t; -#define __DEFINED_uint16_t +typedef unsigned short uint16_t; + #define __DEFINED_uint16_t #endif #if defined(__NEED_uint32_t) && !defined(__DEFINED_uint32_t) -typedef unsigned int uint32_t; -#define __DEFINED_uint32_t +typedef unsigned int uint32_t; + #define __DEFINED_uint32_t #endif #if defined(__NEED_uint64_t) && !defined(__DEFINED_uint64_t) typedef unsigned _Int64 uint64_t; -#define __DEFINED_uint64_t + #define __DEFINED_uint64_t #endif #if defined(__NEED_u_int64_t) && !defined(__DEFINED_u_int64_t) typedef unsigned _Int64 u_int64_t; -#define __DEFINED_u_int64_t + #define __DEFINED_u_int64_t #endif #if defined(__NEED_uintmax_t) && !defined(__DEFINED_uintmax_t) typedef unsigned _Int64 uintmax_t; -#define __DEFINED_uintmax_t + #define __DEFINED_uintmax_t #endif #if defined(__NEED_mode_t) && !defined(__DEFINED_mode_t) typedef unsigned mode_t; -#define __DEFINED_mode_t + #define __DEFINED_mode_t #endif #if defined(__NEED_nlink_t) && !defined(__DEFINED_nlink_t) typedef unsigned _Reg nlink_t; -#define __DEFINED_nlink_t + #define __DEFINED_nlink_t #endif #if defined(__NEED_off_t) && !defined(__DEFINED_off_t) typedef _Int64 off_t; -#define __DEFINED_off_t + #define __DEFINED_off_t #endif #if defined(__NEED_ino_t) && !defined(__DEFINED_ino_t) typedef unsigned _Int64 ino_t; -#define __DEFINED_ino_t + #define __DEFINED_ino_t #endif #if defined(__NEED_dev_t) && !defined(__DEFINED_dev_t) typedef unsigned _Int64 dev_t; -#define __DEFINED_dev_t + #define __DEFINED_dev_t #endif #if defined(__NEED_blksize_t) && !defined(__DEFINED_blksize_t) typedef long blksize_t; -#define __DEFINED_blksize_t + #define __DEFINED_blksize_t #endif #if defined(__NEED_blkcnt_t) && !defined(__DEFINED_blkcnt_t) typedef _Int64 blkcnt_t; -#define __DEFINED_blkcnt_t + #define __DEFINED_blkcnt_t #endif #if defined(__NEED_fsblkcnt_t) && !defined(__DEFINED_fsblkcnt_t) typedef unsigned _Int64 fsblkcnt_t; -#define __DEFINED_fsblkcnt_t + #define __DEFINED_fsblkcnt_t #endif #if defined(__NEED_fsfilcnt_t) && !defined(__DEFINED_fsfilcnt_t) typedef unsigned _Int64 fsfilcnt_t; -#define __DEFINED_fsfilcnt_t + #define __DEFINED_fsfilcnt_t #endif #if defined(__NEED_wctype_t) && !defined(__DEFINED_wctype_t) typedef unsigned long wctype_t; -#define __DEFINED_wctype_t + #define __DEFINED_wctype_t #endif #if defined(__NEED_timer_t) && !defined(__DEFINED_timer_t) typedef void * timer_t; -#define __DEFINED_timer_t + #define __DEFINED_timer_t #endif #if defined(__NEED_clockid_t) && !defined(__DEFINED_clockid_t) typedef int clockid_t; -#define __DEFINED_clockid_t + #define __DEFINED_clockid_t #endif #if defined(__NEED_clock_t) && !defined(__DEFINED_clock_t) typedef long clock_t; -#define __DEFINED_clock_t + #define __DEFINED_clock_t #endif #if defined(__NEED_struct_timeval) && !defined(__DEFINED_struct_timeval) -struct timeval { time_t tv_sec; suseconds_t tv_usec; }; -#define __DEFINED_struct_timeval +struct timeval { + time_t tv_sec; + suseconds_t tv_usec; +}; + #define __DEFINED_struct_timeval #endif #if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec) -struct timespec { time_t tv_sec; long tv_nsec; }; -#define __DEFINED_struct_timespec +struct timespec { + time_t tv_sec; + long tv_nsec; +}; + #define __DEFINED_struct_timespec #endif #if defined(__NEED_pid_t) && !defined(__DEFINED_pid_t) typedef int pid_t; -#define __DEFINED_pid_t + #define __DEFINED_pid_t #endif #if defined(__NEED_id_t) && !defined(__DEFINED_id_t) typedef unsigned id_t; -#define __DEFINED_id_t + #define __DEFINED_id_t #endif #if defined(__NEED_uid_t) && !defined(__DEFINED_uid_t) typedef unsigned uid_t; -#define __DEFINED_uid_t + #define __DEFINED_uid_t #endif #if defined(__NEED_gid_t) && !defined(__DEFINED_gid_t) typedef unsigned gid_t; -#define __DEFINED_gid_t + #define __DEFINED_gid_t #endif #if defined(__NEED_key_t) && !defined(__DEFINED_key_t) typedef int key_t; -#define __DEFINED_key_t + #define __DEFINED_key_t #endif #if defined(__NEED_useconds_t) && !defined(__DEFINED_useconds_t) typedef unsigned useconds_t; -#define __DEFINED_useconds_t + #define __DEFINED_useconds_t #endif #ifdef __cplusplus -#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t) + #if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t) typedef unsigned long pthread_t; -#define __DEFINED_pthread_t -#endif + #define __DEFINED_pthread_t + #endif #else -#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t) + #if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t) typedef struct __pthread * pthread_t; -#define __DEFINED_pthread_t -#endif + #define __DEFINED_pthread_t + #endif #endif #if defined(__NEED_pthread_once_t) && !defined(__DEFINED_pthread_once_t) typedef int pthread_once_t; -#define __DEFINED_pthread_once_t + #define __DEFINED_pthread_once_t #endif #if defined(__NEED_pthread_key_t) && !defined(__DEFINED_pthread_key_t) typedef unsigned pthread_key_t; -#define __DEFINED_pthread_key_t + #define __DEFINED_pthread_key_t #endif #if defined(__NEED_pthread_spinlock_t) && !defined(__DEFINED_pthread_spinlock_t) typedef int pthread_spinlock_t; -#define __DEFINED_pthread_spinlock_t + #define __DEFINED_pthread_spinlock_t #endif #if defined(__NEED_pthread_mutexattr_t) && !defined(__DEFINED_pthread_mutexattr_t) -typedef struct { unsigned __attr; } pthread_mutexattr_t; -#define __DEFINED_pthread_mutexattr_t +typedef struct { + unsigned __attr; +} pthread_mutexattr_t; + #define __DEFINED_pthread_mutexattr_t #endif #if defined(__NEED_pthread_condattr_t) && !defined(__DEFINED_pthread_condattr_t) -typedef struct { unsigned __attr; } pthread_condattr_t; -#define __DEFINED_pthread_condattr_t +typedef struct { + unsigned __attr; +} pthread_condattr_t; + #define __DEFINED_pthread_condattr_t #endif #if defined(__NEED_pthread_barrierattr_t) && !defined(__DEFINED_pthread_barrierattr_t) -typedef struct { unsigned __attr; } pthread_barrierattr_t; -#define __DEFINED_pthread_barrierattr_t +typedef struct { + unsigned __attr; +} pthread_barrierattr_t; + #define __DEFINED_pthread_barrierattr_t #endif #if defined(__NEED_pthread_rwlockattr_t) && !defined(__DEFINED_pthread_rwlockattr_t) -typedef struct { unsigned __attr[2]; } pthread_rwlockattr_t; -#define __DEFINED_pthread_rwlockattr_t +typedef struct { + unsigned __attr[2]; +} pthread_rwlockattr_t; + #define __DEFINED_pthread_rwlockattr_t #endif #if defined(__NEED_FILE) && !defined(__DEFINED_FILE) typedef struct _IO_FILE FILE; -#define __DEFINED_FILE + #define __DEFINED_FILE #endif #if defined(__NEED_locale_t) && !defined(__DEFINED_locale_t) typedef struct __locale_struct * locale_t; -#define __DEFINED_locale_t + #define __DEFINED_locale_t #endif #if defined(__NEED_sigset_t) && !defined(__DEFINED_sigset_t) -typedef struct __sigset_t { unsigned long __bits[128/sizeof(long)]; } sigset_t; -#define __DEFINED_sigset_t +typedef struct __sigset_t { + unsigned long __bits[128 / sizeof(long)]; +} sigset_t; + #define __DEFINED_sigset_t #endif #if defined(__NEED_struct_iovec) && !defined(__DEFINED_struct_iovec) -struct iovec { void *iov_base; size_t iov_len; }; -#define __DEFINED_struct_iovec +struct iovec { + void * iov_base; + size_t iov_len; +}; + #define __DEFINED_struct_iovec #endif #if defined(__NEED_socklen_t) && !defined(__DEFINED_socklen_t) typedef unsigned socklen_t; -#define __DEFINED_socklen_t + #define __DEFINED_socklen_t #endif #if defined(__NEED_sa_family_t) && !defined(__DEFINED_sa_family_t) typedef unsigned short sa_family_t; -#define __DEFINED_sa_family_t + #define __DEFINED_sa_family_t #endif diff --git a/kernel/src/klibc/include/bits/stdint.h b/kernel/src/klibc/include/bits/stdint.h new file mode 100644 index 00000000..7bb2500d --- /dev/null +++ b/kernel/src/klibc/include/bits/stdint.h @@ -0,0 +1,20 @@ +typedef int32_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef uint32_t uint_fast16_t; +typedef uint32_t uint_fast32_t; + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN + +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX + +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX +#define SIZE_MAX UINT32_MAX diff --git a/kernel/src/klibc/include/constants.h b/kernel/src/klibc/include/constants.h new file mode 100644 index 00000000..8227a032 --- /dev/null +++ b/kernel/src/klibc/include/constants.h @@ -0,0 +1,17 @@ +#ifndef CONSTANTS_H +#define CONSTANTS_H + +#include + +/// SI Binary prefixes +#define Kibibyte ((size_t)(1024u)) +#define Mebibyte ((size_t)(Kibibyte * 1024u)) +#define Gibibyte ((size_t)(Mebibyte * 1024u)) +#define Tebibyte ((size_t)(Gibibyte * 1024u)) +#define Pebibyte ((size_t)(Tebibyte * 1024u)) +#define Exbibyte ((size_t)(Pebibyte * 1024u)) +#define Zebibyte ((size_t)(Exbibyte * 1024u)) +#define Yobibyte ((size_t)(Zebibyte * 1024u)) + + +#endif diff --git a/kernel/src/klibc/include/klibc.h b/kernel/src/klibc/include/klibc.h new file mode 100644 index 00000000..595aba83 --- /dev/null +++ b/kernel/src/klibc/include/klibc.h @@ -0,0 +1,124 @@ +/******************************************************************** + * libc.h + * + * (Any collaborators, please add your name) + * Author: Jared McArthur, Taylor Smith, Sheldon Sandbekkhaug, Kaelen Haag + * + * Last edited: 20 April 2014 + * + * Purpose: Provide basic libc funtionality for CourseOS + * This header provides function skeletons + * for libc.c + * + * Usage: Compile into kernel. Adaptations of normal libc functions + * can be used by prepending os_ suffix. + ********************************************************************/ + +/* LOG: + * 3/30 added os_printf function - Taylor Smith + * 4/1 working more on os_printf - Taylor Smith + * 4/20 Added os_memset, os_strchrnul, os_strcpy, os_strlen, os_strtok, + * os_strspn, and os_strcspn from MUSL - Sheldon + * 4/21 Added os_memcpy for loader - Kaelen + * --------------Spring 2015--------------- + * 4/15/15: Added implementation of assert() + */ +#ifndef __KLIBC_H__ +#define __KLIBC_H__ + +#include +#include +#include + +#ifndef __NO_WFI + #define SLEEP \ + while (1) asm volatile("wfi") +#else + #define SLEEP for (;;) +#endif + +typedef unsigned int os_size_t; + + +// 4-17-15: Working assert implementation - Prakash +#define assert(X) \ + { \ + if ((X) || _assert_fail(__FILE__, __LINE__, #X)) \ + ; \ + } + + +char * __strchrnul(char * s, char c); +char * os_strtok(char * s, char * sep); +os_size_t os_strspn(char * s, char * accept); +os_size_t os_strcspn(char * s, char * reject); + +void os_memcpy(uint32_t * source, uint32_t * dest, os_size_t size); + + +uint32_t km_size(); +uint32_t kmcheck(); + + +unsigned int rand(); + +#define UNUSED1(z) (void)(z) +#define UNUSED2(y, z) UNUSED1(y), UNUSED1(z) +#define UNUSED3(x, y, z) UNUSED1(x), UNUSED2(y, z) +#define UNUSED4(b, x, y, z) UNUSED2(b, x), UNUSED2(y, z) +#define UNUSED5(a, b, x, y, z) UNUSED2(a, b), UNUSED3(x, y, z) + +#define VA_NUM_ARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N +#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1) + +#define ALL_UNUSED_IMPL_(nargs) UNUSED##nargs +#define ALL_UNUSED_IMPL(nargs) ALL_UNUSED_IMPL_(nargs) +#define ALL_UNUSED(...) ALL_UNUSED_IMPL(VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__) + + +/// Log level is defined in the Makefile + +#if LOG_LEVEL > 3 + #define TRACE(format, ...) kprintf("\e[90m[TRACE] " format "\e[0m\n", ##__VA_ARGS__) +#else + #define TRACE(...) ALL_UNUSED(__VA_ARGS__) +#endif + +#if LOG_LEVEL > 2 + #define DEBUG(format, ...) \ + kprintf("[DEBUG] \e[92m%s:%i\e[0m " format "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#else + #define DEBUG(...) ALL_UNUSED(__VA_ARGS__) +#endif +#if LOG_LEVEL > 1 + #define INFO(format, ...) kprintf("\e[96m[INFO]\e[0m " format "\n", ##__VA_ARGS__) +#else + #define INFO(...) ALL_UNUSED(__VA_ARGS__) +#endif +#if ENABLE_TESTS + #define WARN(format, ...) \ + kprintf("\e[38;5;208m[WARN] \e[38;5;208m%s:%i\e[38;5;208m" format "\e[0m\n", \ + __FILE__, \ + __LINE__, \ + ##__VA_ARGS__); \ + panic() +#else + #define WARN(format, ...) kprintf("\e[38;5;208m[WARN] " format "\e[0m\n", ##__VA_ARGS__) +#endif + + +#define FATAL(format, ...) \ + kprintf("\e[38;5;160m[FATAL] \e[38;5;208m%s:%i\e[38;5;160m " format "\e[0m\n", \ + __FILE__, \ + __LINE__, \ + ##__VA_ARGS__); \ + panic() + +// 4-17-15: Initial panic * assert_fail functions added +void panic() __attribute__((noreturn)); +int _assert_fail(char * _file, unsigned int _line, char * _func); +//__attribute__ ((__noreturn__)); + +void splash(void); + +#endif diff --git a/kernel/src/klibc/include/math.h b/kernel/src/klibc/include/math.h new file mode 100644 index 00000000..711cdb2e --- /dev/null +++ b/kernel/src/klibc/include/math.h @@ -0,0 +1,11 @@ +#ifndef MATH_H +#define MATH_H + +// useful macros +#define max(a, b) ((a) > (b) ? a : b) +#define min(a, b) ((a) < (b) ? a : b) +#define abs(a) __builtin_abs(a) +//#define abs(a) ((a) > 0 ? (a) : -(a)) + + +#endif diff --git a/kernel/src/klibc/include/stdarg.h b/kernel/src/klibc/include/stdarg.h new file mode 100644 index 00000000..d99b3444 --- /dev/null +++ b/kernel/src/klibc/include/stdarg.h @@ -0,0 +1,25 @@ +#ifndef _STDARG_H +#define _STDARG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_va_list + +#include + +#if __GNUC__ >= 3 + #define va_start(v, l) __builtin_va_start(v, l) + #define va_end(v) __builtin_va_end(v) + #define va_arg(v, l) __builtin_va_arg(v, l) + #define va_copy(d, s) __builtin_va_copy(d, s) +#else + #include +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kernel/src/klibc/include/stdbool.h b/kernel/src/klibc/include/stdbool.h new file mode 100644 index 00000000..4c2d176b --- /dev/null +++ b/kernel/src/klibc/include/stdbool.h @@ -0,0 +1,10 @@ + +#ifndef STDBOOL_H +#define STDBOOL_H + +#define true 1 +#define false 0 + +typedef _Bool bool; + +#endif \ No newline at end of file diff --git a/kernel/src/klibc/include/stdint.h b/kernel/src/klibc/include/stdint.h new file mode 100644 index 00000000..7cd039ab --- /dev/null +++ b/kernel/src/klibc/include/stdint.h @@ -0,0 +1,134 @@ +#ifndef _STDINT_H +#define _STDINT_H + +#define __NEED_int8_t +#define __NEED_int16_t +#define __NEED_int32_t +#define __NEED_int64_t + +#define __NEED_uint8_t +#define __NEED_uint16_t +#define __NEED_uint32_t +#define __NEED_uint64_t + +#define __NEED_intptr_t +#define __NEED_uintptr_t + +#define __NEED_intmax_t +#define __NEED_uintmax_t + +#include + +typedef int8_t int_fast8_t; +typedef int64_t int_fast64_t; + +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; + +typedef uint8_t uint_fast8_t; +typedef uint64_t uint_fast64_t; + +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +#define MACHINE_WORDSIZE 32 + +#if MACHINE_WORDSIZE == 32 +typedef uint32_t size_t; +typedef int32_t isize_t; +#else + #if MACHINE_WORDSIZE == 64 + #error \ + "TODO: we declare some pointers as uint32_t meaning that this mode is not currently supported." +typedef uint64_t size_t; +typedef int64_t isize_t; + #else + #error "WORDSIZE not supported" + #endif +#endif + + +#define INT8_MIN (-1 - 0x7f) +#define INT16_MIN (-1 - 0x7fff) +#define INT32_MIN (-1 - 0x7fffffff) +#define INT64_MIN (-1 - 0x7fffffffffffffff) + +#define INT8_MAX (0x7f) +#define INT16_MAX (0x7fff) +#define INT32_MAX (0x7fffffff) +#define INT64_MAX (0x7fffffffffffffff) + +#define UINT8_MAX (0xff) +#define UINT16_MAX (0xffff) +#define UINT32_MAX (0xffffffff) +#define UINT64_MAX (0xffffffffffffffff) + +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST64_MAX INT64_MAX + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +#define WINT_MIN 0 +#define WINT_MAX UINT32_MAX + +#if L'\0' - 1 > 0 + #define WCHAR_MAX (0xffffffffu + L'\0') + #define WCHAR_MIN (0 + L'\0') +#else + #define WCHAR_MAX (0x7fffffff + L'\0') + #define WCHAR_MIN (-1 - 0x7fffffff + L'\0') +#endif + +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +#include + +#define INT8_C(c) c +#define INT16_C(c) c +#define INT32_C(c) c + +#define UINT8_C(c) c +#define UINT16_C(c) c +#define UINT32_C(c) c##U + +#if UINTPTR_MAX == UINT64_MAX + #define INT64_C(c) c##L + #define UINT64_C(c) c##UL + #define INTMAX_C(c) c##L + #define UINTMAX_C(c) c##UL +#else + #define INT64_C(c) c##LL + #define UINT64_C(c) c##ULL + #define INTMAX_C(c) c##LL + #define UINTMAX_C(c) c##ULL +#endif + +#endif diff --git a/kernel/src/klibc/include/stdio.h b/kernel/src/klibc/include/stdio.h new file mode 100644 index 00000000..d485d615 --- /dev/null +++ b/kernel/src/klibc/include/stdio.h @@ -0,0 +1,35 @@ + +#ifndef STDIO_H +#define STDIO_H + +#ifndef NULL + #define NULL ((void *)0) +#endif + +#define UNUSED(x) (void)(x) + +#include +#include + +/** + * Note: os_printf is restricted to printing only 256 characters. + * Supported format string conversions: + * X: upper-case hexadecimal print. + * x: lower-case hexadecimal print. + * d: signed integer. + * u: unsigned integer. + * c: ASCII character. + * s: string. + * %: the percent sign itself. + * + * Supported options: + * 0: zero-pad the result (applies to X,x,d,u). For example: + * os_printf("'%05d %05d %05u'\n", 15, -15, -15); + * prints '00015 -0015 4294967281' + */ +int os_vsnprintf(char * buf, int buflen, const char * str_buf, va_list args); +int os_snprintf(char * buf, int buflen, const char * fmt_string, ...); +int kprintf(const char * str_buf, ...); + + +#endif diff --git a/kernel/src/klibc/include/stdlib.h b/kernel/src/klibc/include/stdlib.h new file mode 100644 index 00000000..6e54e597 --- /dev/null +++ b/kernel/src/klibc/include/stdlib.h @@ -0,0 +1,42 @@ +#ifndef STDLIB_H +#define STDLIB_H + +#include + +void * kmalloc(uint32_t size); +void * kmalloc_aligned(uint32_t size, uint32_t alignment); +void kfree(void * ptr); +void * krealloc(void * ptr, uint32_t size); +void * kcalloc(size_t n, size_t size); + +/** + * umalloc allocates memory on the user heap + * + * @param size of the block of memory allocated + * @param uint32_t size + * @return returns a pointer to the allocated block of memory + */ +void * umalloc(uint32_t size); // does user level malloc work + +/** + * ualigned alloc allocates memory on the user heap + * according to a specified alignemnt + * + * @param size of the block of memory allocated, and alignment desired + * @param uint32_t size, uint32_alignment + * @return returns a pointer to the allocated block of memory + * that is a multiple of the specified allignement + */ +void * ualigned_alloc(uint32_t size, uint32_t alignment); // does user level aligned_alloc work + +/** + * free's an allocated block of memory on the heap + * + * @param pointer to a block of memeory on the heap + * @param void* ptr + * @return nothing returned + */ +void ufree(void *); // does user level free work + + +#endif diff --git a/kernel/src/klibc/include/string.h b/kernel/src/klibc/include/string.h new file mode 100644 index 00000000..edb08f71 --- /dev/null +++ b/kernel/src/klibc/include/string.h @@ -0,0 +1,19 @@ +#ifndef STRING_H +#define STRING_H + +#include +#include + +char * strcpy(char * dst, char * src); +char * strncpy(char * dest, char * src, size_t n); +uint32_t strcmp(char * s1, char * s2); +uint32_t strlen(char * str); +uint32_t strncmp(char * s1, char * s2, size_t n); + +void * memcpy(void * dest, void * src, size_t count); +void * memset(void * dest, uint32_t val, size_t count); +uint16_t * memsetw(uint16_t * dest, uint16_t val, size_t count); +void * memmove(void * dest, const void * src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); + +#endif diff --git a/kernel/src/klibc/klibc.c b/kernel/src/klibc/klibc.c new file mode 100644 index 00000000..5cd5ccba --- /dev/null +++ b/kernel/src/klibc/klibc.c @@ -0,0 +1,353 @@ +/******************************************************************** + * klibc.c + * + * (Any collaborators, please add your name) + * Author: Jared McArthur, Taylor Smith, Sheldon Sandbekkhaug, Kaelen Haag, Collin Massey + * + * Last edited: 4 December 2015 + * + * Purpose: Provide basic libc funtionality for CourseOS + * This file provides function implementations + * for skels in libc.h + * + * Usage: Compile into kernel. Adaptations of normal libc functions + * can be used by prepending os_ suffix. + * + * Notes: The following were adapted directly from musl-libc: + * memcmp, memset, strcmp, strchrnul, strcpy, strlen, strtok + ********************************************************************/ +#include +#include +#include +#include +#include + +// FIXME: decouple +#include + +#define LOWER_CASE 0 +#define UPPER_CASE 1 +#define NO_CASE 2 + +// Helpers for MUSL String functions +#define UCHAR_MAX 0xFF +#define ALIGN (sizeof(os_size_t)) +#define ONES ((os_size_t)-1 / UCHAR_MAX) +#define HIGHS (ONES * (UCHAR_MAX / 2 + 1)) +#define HASZERO(x) (((x)-ONES) & (~(x)) & HIGHS) + +// Currrently states the panic and stalls the machine or exits iff run within qemu with semihosting +// enabled. +void inline panic() { + disable_interrupt(BOTH); + kprintf("Kernel panic!\n"); + kprintf("\n ) ( \n"); + kprintf(" ( /( ( )\\ ) \n"); + kprintf(" )\\()) ( ( ( )\\ (()/( ) ( \n"); + kprintf("|((_)\\ ))\\ )( ( ))((_) /(_)| /( ( )\\ ( \n"); + kprintf("|_ ((_)((_|()\\ )\\ ) /((_) (_)) )(_)) )\\ |(_) )\\ \n"); + kprintf("| |/ (_)) ((_)_(_/((_))| | | _ ((_)_ _(_/((_)((_) \n"); + kprintf(" ' = '0' && *string <= '9') { + integer *= 10; + integer += (*string - '0'); + } else { + return 0; + } + } + return sign * integer; +} + +// Return string converted to double form, or 0 if not applicable +double katof(char * string) { + if (!string) return 0.0; + + double integer = 0.0; // before decimal + double fraction = 0.0; // after decimal + int sign = 1; // positive or negative? + int divisor = 1; // used to push fraction past decimal point + bool after_decimal = false; // decimal point reached? + + // Check if string includes sign (including a "+") + if (*string == '-') { + sign = -1; + string++; // progress to next char + } else if (*string == '+') { + string++; + } + + while (*string != '\0') { + if (*string >= '0' && *string <= '9') { + if (after_decimal) { + fraction *= 10; // progress to next position in integer + fraction += (*string - '0'); // add integer form of current number in string + divisor *= 10; + } else { + integer *= 10; // progress to next position in integer + integer += (*string - '0'); // add integer form of current number in string + } + } else if (*string == '.') { + if (after_decimal) return 0.0; // more than one '.' + after_decimal = true; + } else { + return 0.0; // current char in string is not a number or '.' + } + string++; + } + return sign * (integer + (fraction / divisor)); +} + +// Return string converted to long int form, or 0 if not applicable +long int katol(char * string) { + return (long int)katoi(string); +} + +/* +// Same a +#include "../../old/include/klibc.h"s katof, but makes endptr point to the string which comes after +the number double kstrtod(const char *string, char **endptr) +{ + if (!string) + return 0.0; + + double integer = 0.0; + double fraction = 0.0; + int sign = 1; + int divisor = 1; + Boolean after_decimal = FALSE; + Boolean result_found = FALSE; + double result = 0.0; + + if (*string == '-') + { + sign = -1; + string++; + } + else if (*string == '+') + string++; +} + +while (!result_found) +{ + if (*string >= '0' && *string <= '9') + { + if (after_decimal) + { + fraction *= 10; + fraction += (*string - '0'); + divisor *= 10; + } + else + { + integer *= 10; + integer += (*string - '0'); + } + string++; + } + else if (*string == '.') + { + if (after_decimal) + return 0.0; + after_decimal = true; + string++; + } + else + { + result = sign * (integer + (fraction/divisor)); + result_found = true; + } +} + +*endptr = string; + +return result; +} +*/ + +// Same as katol, but makes endptr point to the string which comes after the number +long int kstrtol(char * string, char ** endptr) { + if (!string) return 0; + + long int integer = 0; + long int result = 0; + bool result_found = false; + int sign = 1; + + if (*string == '-') { + sign = -1; + string++; + } else if (*string == '+') { + string++; + } + + while (!result_found) { + if (*string >= '0' && *string <= '9') { + integer *= 10; + integer += (*string - '0'); + string++; + } else { + result = sign * integer; + result_found = true; + } + } + *endptr = (char *)string; + + return result; +} + +// NOTE potentially expand these features. offer more +// memory stats +uint32_t km_size() { + return mem_get_heap_size(); +} + + +unsigned int rand() { + static unsigned int z1 = 12345, z2 = 67891, z3 = 11121, z4 = 31415; + unsigned int b; + b = ((z1 << 6) ^ z1) >> 13; + z1 = ((z1 & 4294967294U) << 18) ^ b; + b = ((z2 << 2) ^ z2) >> 27; + z2 = ((z2 & 4294967288U) << 2) ^ b; + b = ((z3 << 13) ^ z3) >> 21; + z3 = ((z3 & 4294967280U) << 7) ^ b; + b = ((z4 << 3) ^ z4) >> 12; + z4 = ((z4 & 4294967168U) << 13) ^ b; + return (z1 ^ z2 ^ z3 ^ z4); +} diff --git a/kernel/src/klibc/mem.c b/kernel/src/klibc/mem.c new file mode 100644 index 00000000..925995b2 --- /dev/null +++ b/kernel/src/klibc/mem.c @@ -0,0 +1,29 @@ +#include + +void * memcpy(void * dest, void * src, size_t count) { + const char * sp = (const char *)src; + char * dp = (char *)dest; + for (; count != 0; count--) *dp++ = *sp++; + return dp; +} + +void * memset(void * dest, uint32_t val, size_t count) { + char * temp = (char *)dest; + for (; count != 0; count--) *temp++ = (char)val; + return dest; +} + +uint16_t * memsetw(uint16_t * dest, uint16_t val, size_t count) { + uint16_t * temp = (uint16_t *)dest; + for (; count != 0; count--) *temp++ = val; + return dest; +} + +void * memmove(void * dest, const void * src, size_t n) { + unsigned char tmp[n]; + + memcpy(tmp, (void *)src, n); + memcpy(dest, tmp, n); + + return dest; +} diff --git a/kernel/src/klibc/printf.c b/kernel/src/klibc/printf.c new file mode 100644 index 00000000..75886412 --- /dev/null +++ b/kernel/src/klibc/printf.c @@ -0,0 +1,184 @@ +#include +#include +#include + +static char lower_case_digits[16] = "0123456789abcdef"; +static char upper_case_digits[16] = "0123456789ABCDEF"; + +// base is between 2 and 16, inclusive +int print_int(char * buf, + int buflen, + int val, + int base, + int is_unsigned, + int padding, + char pad_char, + int is_uppercase) { + int max_len = buflen; + int orig_max_len = max_len; + int negate = 0; + if (val < 0 && !is_unsigned) { + val = -val; + negate = 1; + } + unsigned int temp = val; + + if (max_len == 0) return orig_max_len - max_len; + if (negate) { + *buf = '-'; + buf++; + max_len--; + if (max_len == 0) return orig_max_len - max_len; + } + + char tmp_buf[64]; + int ndigits = 0; + while (temp != 0) { + if (is_uppercase) { + tmp_buf[ndigits] = upper_case_digits[temp % base]; + } else { + tmp_buf[ndigits] = lower_case_digits[temp % base]; + } + temp = temp / base; + ndigits++; + } + + // Zero-pad the output + int i; + if (padding > 0) { + for (i = 0; i < padding - ndigits - negate; i++) { + *buf = pad_char; + buf++; + max_len--; + if (max_len == 0) return orig_max_len; + } + } + + // Output the digits + for (i = ndigits - 1; i >= 0; i--) { + *buf = tmp_buf[i]; + buf++; + max_len--; + if (max_len == 0) return orig_max_len; + } + if (ndigits == 0 && padding <= 0) { + *buf = '0'; + buf++; + max_len--; + if (max_len == 0) return orig_max_len; + } + + return orig_max_len - max_len; +} + +// args must already have been started +// TODO: properly stop at buflen. Otherwise there is a buffer overflow. +int os_vsnprintf(char * buf, int buflen, const char * str_buf, va_list args) { + if (buflen == 0) return 0; + buflen--; + if (buflen == 0) { + buf[0] = 0; + return 1; + } + int nwritten = 0; + int t_arg; + char * str_arg; + int padding = -1; + char pad_char = 0; + while (*str_buf != '\0') { + int n = 0; + if (*str_buf == '%') { + str_buf++; + // This label is where we go after we've read an option. + reread_switch:; + switch (*str_buf) { + case '0': + // Zero-padding... Read all the numbers. + // Then restart the switch statement. + padding = 0; + pad_char = '0'; + while (*str_buf <= '9' && *str_buf >= '0') { + padding *= 10; + padding += *str_buf - '0'; + str_buf++; + } + goto reread_switch; + break; + case 'X': + t_arg = va_arg(args, int); + n = print_int(buf, buflen, t_arg, 16, 1, padding, pad_char, 1); + break; + case 'x': + t_arg = va_arg(args, int); + n = print_int(buf, buflen, t_arg, 16, 1, padding, pad_char, 0); + break; + case 'd': + case 'i': + t_arg = va_arg(args, int); + n = print_int(buf, buflen, t_arg, 10, 0, padding, pad_char, 0); + break; + case 'u': + t_arg = va_arg(args, int); + n = print_int(buf, buflen, t_arg, 10, 1, padding, pad_char, 0); + break; + case 'c': + t_arg = va_arg(args, int); + *buf = t_arg; + n = 1; + break; + case 's': + str_arg = va_arg(args, char *); + strncpy(buf, str_arg, buflen); + n = strlen(str_arg); + if (n > buflen) { n = buflen; } + break; + case '%': + *buf = '%'; + n = 1; + break; + } + // Reset all the options + padding = -1; + } else { + *buf = *str_buf; + n = 1; + } + buf += n; + buflen -= n; + nwritten += n; + if (buflen <= 0) { + // Return! + break; + } + str_buf++; + } + buf[0] = 0; + nwritten++; + + return nwritten; +} + +int os_snprintf(char * buf, int buflen, const char * fmt, ...) { + va_list args; + va_start(args, fmt); + int n = os_vsnprintf(buf, buflen, fmt, args); + va_end(args); + return n; +} + +void puts(const char * s) { + while (*s != '\0') { + chipset.uart_putc(*s, 0); + s++; + } +} + +int kprintf(const char * str_buf, ...) { + va_list args; + va_start(args, str_buf); + char buf[256]; + int n = os_vsnprintf(buf, 255, str_buf, args); + va_end(args); + puts(buf); + return n; +} diff --git a/kernel/src/klibc/string.c b/kernel/src/klibc/string.c new file mode 100644 index 00000000..8287b649 --- /dev/null +++ b/kernel/src/klibc/string.c @@ -0,0 +1,86 @@ +#include + +char * strcpy(char * dst, char * src) { + uint32_t i; + for (i = 0; src[i] != 0; i++) { dst[i] = src[i]; } + dst[i] = 0; + return dst; +} + +char * strncpy(char * dest, char * src, size_t n) { + char * s = (char *)src; + char * d = (char *)dest; + while ((*d++ = *s++) && n--) + ; + return dest; +} + +char * strcat(char * dst, char * src) { + uint32_t i = 0; + uint32_t j = 0; + for (i = 0; dst[i] != 0; i++) + ; + for (j = 0; src[j] != 0; j++) { dst[i + j] = src[j]; } + dst[i + j] = 0; + return dst; +} + +char * strcatc(char * dst, char src) { + uint32_t i = 0; + for (i = 0; dst[i] != 0; i++) + ; + dst[i + 0] = src; + dst[i + 1] = 0; + return dst; +} + +uint32_t strcmp(char * s1, char * s2) { + for (uint32_t i = 0;; i++) { + if (s1[i] != s2[i]) { return s1[i] < s2[i] ? -1 : 1; } + + if (s1[i] == '\0') { return 0; } + } +} + +uint32_t strncmp(char * s1, char * s2, size_t n) { + while (n && *s1 && (*s1 == *s2)) { + ++s1; + ++s2; + --n; + } + if (n == 0) { + return 0; + } else { + return (*(uint8_t *)s1 - *(uint8_t *)s2); + } +} + +uint32_t strlen(char * str) { + for (uint32_t i = 0;; i++) { + if (str[i] == '\0') { return i; } + } + return 0; +} + +bool starts_with(char * s1, char * s2) { + if (strncmp(s1, s2, strlen(s2)) == 0) { return true; } + return false; +} + +/* + * Implementation taken from FreeBSD under BSD-3-Clause license. + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + */ +int memcmp(const void *s1, const void *s2, size_t n) { + if (n != 0) { + const unsigned char *p1 = s1, *p2 = s2; + + do { + if (*p1++ != *p2++) + return (*--p1 - *--p2); + } while (--n != 0); + } + return (0); +} diff --git a/kernel/src/process/asm_helper.s b/kernel/src/process/asm_helper.s new file mode 100644 index 00000000..64800c76 --- /dev/null +++ b/kernel/src/process/asm_helper.s @@ -0,0 +1,54 @@ +.text + .global switch_context, store_context + +switch_context: + // Set the CPSR register. + ldr r1, [r0, #16] + msr cpsr, r1 + // Load the stack pointer. + ldr sp, [r0, #52] + // Push all other registers on the stack. + ldr r1, [r0, #64] + push {r1} + ldr r1, [r0, #60] + push {r1} + ldr r1, [r0, #56] + push {r1} + ldr r1, [r0, #48] + push {r1} + ldr r1, [r0, #44] + push {r1} + ldr r1, [r0, #40] + push {r1} + ldr r1, [r0, #36] + push {r1} + ldr r1, [r0, #32] + push {r1} + ldr r1, [r0, #28] + push {r1} + ldr r1, [r0, #24] + push {r1} + ldr r1, [r0, #20] + push {r1} + ldr r1, [r0, #16] + push {r1} + ldr r1, [r0, #12] + push {r1} + ldr r1, [r0, #8] + push {r1} + ldr r1, [r0, #4] + push {r1} + ldr r1, [r0, #0] + push {r1} + + // TODO: Enter user mode + // cps #16 + + // Load all register states. + // Loading the PC register effectively jumps into the user program + ldm sp!,{R0-R12,r14-pc}^ + +store_context: + // TODO: somehow make sure to store the context, without overriding unstored registers. + // The registers probably have been overriden just by calling this function. + mov pc, lr diff --git a/kernel/src/process/elf.c b/kernel/src/process/elf.c new file mode 100644 index 00000000..c4731732 --- /dev/null +++ b/kernel/src/process/elf.c @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include + +Elf *elf_parse_header(Elf * elf, ElfRawHeader *elf_raw_header); +ElfSection *elf_parse_section(Elf * elf, ElfRawSection *elf_raw_section); +Elf *elf_parse_program(Elf *elf, ElfRawProgram *elf_raw_program); + +/** + * Parse a binary array as ELF file. + * Returns NULL if invalid. + */ +Elf *elf_decode(void *binary, int length) { + TRACE("[ELF] Starting parsing of an ELF file."); + Elf *elf = kmalloc(sizeof(Elf)); + elf->binary = binary; + + // Parse the header + ElfRawHeader *header = (void *) binary; + if(elf_parse_header(elf, header) == NULL) { + kfree(elf); + return NULL; + } + + // Parse sections + for(int i = 0; i < header->e_shnum; i++) { + ElfRawSection *rawSection = (void *) binary + header->e_shoff + (i * header->e_shentsize); + ElfSection *section = elf_parse_section(elf, rawSection); + + if(section == NULL) { + kfree(elf); + return NULL; + } + + vpa_push(elf->sections, section); + } + + // Parse program + ElfRawProgram *rawProgram = (void *) binary + header->e_phoff; + if(elf_parse_program(elf, rawProgram) == NULL) { + kfree(elf); + return NULL; + } + + return elf; +} + +/** + * Parse the header of the ELF file. + * Returns null if the file was invalid. + */ +Elf *elf_parse_header(Elf *elf, ElfRawHeader *elf_raw_header) { + // Check the magic bytes + char magic_byte[] = {0x7f, 0x45, 0x4c, 0x46}; + if(memcmp(elf_raw_header->e_ident, magic_byte, 4) != 0) { + WARN("[ELF] Invalid magic bytes."); + return NULL; + } + + // Check the file class + if(elf_raw_header->e_ident[4] != 0x01) { + WARN("[ELF] ELF file not made for 32-bit devices."); + return NULL; + } + + // Check the data encoding + if(elf_raw_header->e_ident[5] != 0x01) { + WARN("[ELF] ELF file not in the correct data encoding."); + return NULL; + } + + // Check the file version + if(elf_raw_header->e_ident[6] != 0x01) { + WARN("[ELF] ELF file does not have the correct version."); + return NULL; + } + + // Check the type of file + if(elf_raw_header->e_type != 0x02) { + WARN("[ELF] ELF file is not an executable."); + return NULL; + } + + // Check the target machine + if(elf_raw_header->e_machine != 0x28) { + WARN("[ELF] ELF file is not targeted for ARM."); + return NULL; + } + + // Check the version + if(elf_raw_header->e_version != 0x01) { + WARN("[ELF] ELF file does not have the correct version."); + return NULL; + } + + // Check the program headers + if(elf_raw_header->e_phnum != 0x01) { + WARN("[ELF] ELF files with more than one program header are currently unsupported."); + return NULL; + } + + elf->entry = (void *) elf_raw_header->e_entry; + TRACE("[ELF] Executable entry defined on: 0x%x.", elf->entry); + + elf->sections = vpa_create(elf_raw_header->e_shnum); + TRACE("[ELF] Amount of sections: %i.", elf_raw_header->e_shnum); + + return elf; +} + +ElfSection *elf_parse_section(Elf *elf, ElfRawSection *elf_raw_section) { + ElfSection *section = kmalloc(sizeof(ElfSection)); + + section->address = (void *) elf_raw_section->sh_addr; + TRACE("[ELF] Section address start: 0x%x.", section->address); + + section->offset = (void *) elf_raw_section->sh_offset; + TRACE("[ELF] Section file offset: 0x%x.", section->offset); + + section->size = elf_raw_section->sh_size; + TRACE("[ELF] Section size: %i bytes.", section->size); + + section->writable = (bool) elf_raw_section->sh_flags & 0x1; + TRACE("[ELF] Section writable: %i.", section->writable); + + section->allocate = (bool) ((elf_raw_section->sh_flags & 0x2) >> 1); + TRACE("[ELF] Section needs allocation: %i.", section->allocate); + + section->instructions = (bool) ((elf_raw_section->sh_flags & 0x4) >> 2); + TRACE("[ELF] Section contains instructions: %i.", section->instructions); + + TRACE("[ELF] *** End parsing Section ***"); + return section; +} + +Elf *elf_parse_program(Elf *elf, ElfRawProgram *elf_raw_program) { + if(elf_raw_program->p_type != 0x01) { + WARN("[ELF] Non-loadable segments are currently unsupported."); + return NULL; + } + + elf->program.file_offset = elf_raw_program->p_offset; + TRACE("[ELF] Program file offset: 0x%x.", elf->program.file_offset); + + elf->program.mem_location = elf_raw_program->p_vaddr; + TRACE("[ELF] Program memory location: 0x%x.", elf->program.mem_location); + + elf->program.file_size = elf_raw_program->p_filesz; + TRACE("[ELF] Program file size: 0x%x.", elf->program.file_size); + + elf->program.mem_size = elf_raw_program->p_memsz; + TRACE("[ELF] Program memory size: 0x%x.", elf->program.mem_size); + + if(elf->program.file_size != elf->program.mem_size) { + WARN("[ELF] File size is unequal to the memory size. We don't yet know how to handle that."); + return NULL; + } + + return elf; +} + +/** + * Free a ELF section struct. + */ +void elf_section_free(ElfSection *section) { + if(section == NULL) return; + + kfree(section); +} + +/** + * Free a ELF struct. + */ +void elf_free(Elf *elf) { + vpa_free(elf->sections, (FreeFunc) elf_section_free); + kfree(elf); +} diff --git a/kernel/src/process/elf_files.c b/kernel/src/process/elf_files.c new file mode 100644 index 00000000..0fa6e6a8 --- /dev/null +++ b/kernel/src/process/elf_files.c @@ -0,0 +1,2161 @@ +unsigned char swi[] = { + 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0xb4, 0x84, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x34, 0x00, 0x20, 0x00, 0x01, 0x00, 0x28, 0x00, + 0x0e, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x80, 0x00, 0x00, 0x24, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0xb0, 0x2d, 0xe5, 0x00, 0xb0, 0x8d, 0xe2, 0x10, 0x10, 0x9f, 0xe5, 0x2a, 0x20, 0xa0, 0xe3, + 0x00, 0x20, 0x91, 0xe5, 0x04, 0x70, 0xa0, 0xe3, 0x00, 0x00, 0x00, 0xef, 0xf9, 0xff, 0xff, 0xea, + 0x00, 0x80, 0x00, 0x80, 0x47, 0x43, 0x43, 0x3a, 0x20, 0x28, 0x47, 0x4e, 0x55, 0x29, 0x20, 0x39, + 0x2e, 0x32, 0x2e, 0x30, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x01, 0x4e, 0x00, 0x00, 0x00, 0x0c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x05, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x9c, + 0x03, 0x04, 0x05, 0x69, 0x6e, 0x74, 0x00, 0x00, 0x01, 0x11, 0x01, 0x25, 0x0e, 0x13, 0x0b, 0x03, + 0x0e, 0x1b, 0x0e, 0x11, 0x01, 0x12, 0x06, 0x10, 0x17, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x3f, 0x19, + 0x03, 0x0e, 0x3a, 0x0b, 0x3b, 0x0b, 0x39, 0x0b, 0x49, 0x13, 0x11, 0x01, 0x12, 0x06, 0x40, 0x18, + 0x97, 0x42, 0x19, 0x00, 0x00, 0x03, 0x24, 0x00, 0x0b, 0x0b, 0x3e, 0x0b, 0x03, 0x08, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x01, 0xfb, 0x0e, 0x0d, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x2e, 0x2f, 0x73, 0x77, + 0x69, 0x00, 0x00, 0x73, 0x77, 0x69, 0x2e, 0x63, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x0c, 0x00, + 0x05, 0x02, 0x00, 0x80, 0x00, 0x00, 0x01, 0x05, 0x09, 0x00, 0x02, 0x04, 0x01, 0x4c, 0x02, 0x0e, + 0x00, 0x01, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x02, 0x7c, + 0x0e, 0x0c, 0x0d, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x42, 0x0e, 0x04, 0x8b, 0x01, 0x42, 0x0d, 0x0b, 0x2f, 0x68, 0x6f, 0x6d, + 0x65, 0x2f, 0x64, 0x73, 0x6c, 0x75, 0x69, 0x6a, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x6a, 0x2f, 0x73, + 0x72, 0x63, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, + 0x6c, 0x6c, 0x65, 0x72, 0x6d, 0x65, 0x79, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x75, 0x72, 0x73, 0x65, + 0x5f, 0x6f, 0x73, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x00, 0x2e, 0x2f, 0x73, 0x77, 0x69, 0x2f, 0x73, + 0x77, 0x69, 0x2e, 0x63, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x47, 0x4e, 0x55, 0x20, 0x43, 0x39, + 0x39, 0x20, 0x39, 0x2e, 0x32, 0x2e, 0x30, 0x20, 0x2d, 0x6d, 0x63, 0x70, 0x75, 0x3d, 0x61, 0x72, + 0x6d, 0x31, 0x31, 0x37, 0x36, 0x6a, 0x7a, 0x2d, 0x73, 0x20, 0x2d, 0x6d, 0x63, 0x70, 0x75, 0x3d, + 0x61, 0x72, 0x6d, 0x31, 0x31, 0x37, 0x36, 0x6a, 0x7a, 0x66, 0x2d, 0x73, 0x20, 0x2d, 0x6d, 0x66, + 0x70, 0x75, 0x3d, 0x76, 0x66, 0x70, 0x20, 0x2d, 0x6d, 0x61, 0x72, 0x6d, 0x20, 0x2d, 0x6d, 0x61, + 0x72, 0x63, 0x68, 0x3d, 0x61, 0x72, 0x6d, 0x76, 0x36, 0x7a, 0x6b, 0x20, 0x2d, 0x67, 0x20, 0x2d, + 0x4f, 0x30, 0x20, 0x2d, 0x73, 0x74, 0x64, 0x3d, 0x67, 0x6e, 0x75, 0x39, 0x39, 0x20, 0x2d, 0x66, + 0x66, 0x72, 0x65, 0x65, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x2d, 0x66, 0x70, + 0x69, 0x63, 0x00, 0x41, 0x2e, 0x00, 0x00, 0x00, 0x61, 0x65, 0x61, 0x62, 0x69, 0x00, 0x01, 0x24, + 0x00, 0x00, 0x00, 0x05, 0x36, 0x5a, 0x4b, 0x00, 0x06, 0x07, 0x08, 0x01, 0x09, 0x01, 0x12, 0x04, + 0x14, 0x01, 0x15, 0x01, 0x17, 0x03, 0x18, 0x01, 0x19, 0x01, 0x1a, 0x01, 0x1e, 0x06, 0x22, 0x01, + 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xf1, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x24, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x24, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x24, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x01, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x24, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x01, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x01, 0x00, 0x38, 0x00, 0x00, 0x00, 0x24, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x24, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x01, 0x00, 0x47, 0x00, 0x00, 0x00, 0x24, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x01, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x01, 0x00, 0x53, 0x00, 0x00, 0x00, 0x24, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x01, 0x00, 0x00, 0x73, 0x77, 0x69, 0x2e, 0x63, 0x00, 0x24, 0x61, 0x00, 0x24, 0x64, + 0x00, 0x5f, 0x5f, 0x62, 0x73, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x5f, 0x00, 0x5f, + 0x5f, 0x62, 0x73, 0x73, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x5f, 0x00, 0x5f, 0x5f, 0x62, 0x73, 0x73, + 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x5f, 0x5f, 0x65, 0x6e, + 0x64, 0x5f, 0x5f, 0x00, 0x5f, 0x65, 0x64, 0x61, 0x74, 0x61, 0x00, 0x5f, 0x65, 0x6e, 0x64, 0x00, + 0x5f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x00, 0x5f, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x00, 0x00, 0x2e, 0x73, 0x79, 0x6d, 0x74, 0x61, 0x62, 0x00, 0x2e, 0x73, 0x74, + 0x72, 0x74, 0x61, 0x62, 0x00, 0x2e, 0x73, 0x68, 0x73, 0x74, 0x72, 0x74, 0x61, 0x62, 0x00, 0x2e, + 0x74, 0x65, 0x78, 0x74, 0x00, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x2e, 0x64, + 0x65, 0x62, 0x75, 0x67, 0x5f, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x00, 0x2e, 0x64, 0x65, + 0x62, 0x75, 0x67, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x00, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, + 0x61, 0x62, 0x62, 0x72, 0x65, 0x76, 0x00, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x6c, 0x69, + 0x6e, 0x65, 0x00, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x00, + 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x73, 0x74, 0x72, 0x00, 0x2e, 0x41, 0x52, 0x4d, 0x2e, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x00, 0x2e, 0x6e, 0x6f, 0x69, 0x6e, + 0x69, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x80, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x80, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x55, 0x80, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x80, 0x00, 0x00, + 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xd1, 0x80, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x81, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x81, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x82, 0x00, 0x00, + 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x24, 0x80, 0x01, 0x00, 0x32, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x82, 0x00, 0x00, + 0x90, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc4, 0x83, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x84, 0x00, 0x00, + 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; +unsigned int swi_len = 34532; diff --git a/kernel/src/process/include/asm_helper.h b/kernel/src/process/include/asm_helper.h new file mode 100644 index 00000000..6902f0c3 --- /dev/null +++ b/kernel/src/process/include/asm_helper.h @@ -0,0 +1,8 @@ +#ifndef COURSE_OS_ASM_HELPER_H +#define COURSE_OS_ASM_HELPER_H + +#include "./registers.h" + +void switch_context(Registers * registers); + +#endif // COURSE_OS_ASM_HELPER_H diff --git a/kernel/src/process/include/elf.h b/kernel/src/process/include/elf.h new file mode 100644 index 00000000..56a6be5e --- /dev/null +++ b/kernel/src/process/include/elf.h @@ -0,0 +1,81 @@ +#ifndef COURSE_OS_ELF_H +#define COURSE_OS_ELF_H + +#include +#include + +// Taken from: http://www.skyfree.org/linux/references/ELF_Format.pdf +#define EI_NIDENT 16 +#define Elf32_Addr uint32_t +#define Elf32_Half uint16_t +#define Elf32_Off uint32_t +#define Elf32_Sword uint32_t +#define Elf32_Word uint32_t + +typedef struct ElfProgram { + uint32_t file_offset; + uint32_t file_size; + uint32_t mem_location; + uint32_t mem_size; +} ElfProgram; + +typedef struct ElfSection { + void *address; + void *offset; + uint32_t size; + bool writable; + bool allocate; + bool instructions; +} ElfSection; + +typedef struct Elf { + void *entry; + void *binary; + VPArrayList *sections; + ElfProgram program; +} Elf; + +typedef struct ElfRawHeader { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} ElfRawHeader; + +typedef struct ElfRawProgram { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_a; +} ElfRawProgram; + +typedef struct ElfRawSection { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} ElfRawSection; + +Elf *elf_decode(void *binary, int length); + +#endif //COURSE_OS_ELF_H diff --git a/kernel/src/process/include/elf_files.h b/kernel/src/process/include/elf_files.h new file mode 100644 index 00000000..3633b2f9 --- /dev/null +++ b/kernel/src/process/include/elf_files.h @@ -0,0 +1,7 @@ +#ifndef COURSE_OS_ELF_FILES_H +#define COURSE_OS_ELF_FILES_H + +unsigned int swi_len; +unsigned char swi[34532]; + +#endif // COURSE_OS_ELF_FILES_H diff --git a/kernel/src/process/include/process.h b/kernel/src/process/include/process.h new file mode 100644 index 00000000..58bbe8a4 --- /dev/null +++ b/kernel/src/process/include/process.h @@ -0,0 +1,23 @@ +#ifndef COURSE_OS_PROCESS_H +#define COURSE_OS_PROCESS_H + +#include +#include +#include + +#define MAX_PROCESS_PRIORITY 20 +#define DEFAULT_PROCESS_PRIORITY 10 + +typedef struct Process { + uint8_t priority; + size_t pid; + uint8_t exit_code; + struct vas2* vas; + VPArrayList *threads; + struct Process *parent; +} Process; + +Process *create_process(Elf *entry, Process *parent); +void free_process(Process *process); + +#endif //COURSE_OS_PROCESS_H diff --git a/kernel/src/process/include/registers.h b/kernel/src/process/include/registers.h new file mode 100644 index 00000000..94b5b7ae --- /dev/null +++ b/kernel/src/process/include/registers.h @@ -0,0 +1,50 @@ +#ifndef COURSE_OS_REGISTERS_H +#define COURSE_OS_REGISTERS_H + +#include + +typedef struct Registers { + size_t R0; + size_t R1; + size_t R2; + size_t R3; + size_t R4; + size_t R5; + size_t R6; + union { + size_t R7; + size_t WR; + }; + size_t R8; + union { + size_t R9; + size_t SB; + }; + union { + size_t R10; + size_t SL; + }; + union { + size_t R11; + size_t FP; + }; + union { + size_t R12; + size_t IP; + }; + union { + size_t R13; + size_t SP; + }; + union { + size_t R14; + size_t LR; + }; + union { + size_t R15; + size_t PC; + }; + size_t CPSR; +} Registers; + +#endif //COURSE_OS_REGISTERS_H diff --git a/kernel/src/process/include/scheduler.h b/kernel/src/process/include/scheduler.h new file mode 100644 index 00000000..a7c1bcd1 --- /dev/null +++ b/kernel/src/process/include/scheduler.h @@ -0,0 +1,18 @@ +#ifndef COURSE_OS_SCHEDULER_H +#define COURSE_OS_SCHEDULER_H + +#include + +typedef struct Scheduler { + Thread * current_thread; +} Scheduler; + +Scheduler * create_scheduler(); +void enable_scheduler(Scheduler * scheduler); +Scheduler * get_scheduler(); +void schedule_task(Scheduler * scheduler); +void add_process_to_scheduler(Scheduler * scheduler, Process * process); +Thread * get_thread(Scheduler * scheduler); +void free_scheduler(Scheduler * scheduler); + +#endif // COURSE_OS_SCHEDULER_H diff --git a/kernel/src/process/include/syscall.h b/kernel/src/process/include/syscall.h new file mode 100644 index 00000000..d83c0c74 --- /dev/null +++ b/kernel/src/process/include/syscall.h @@ -0,0 +1,9 @@ +#ifndef SYSCALL_H +#define SYSCALL_H + +#define SYSCAL_EXIT 1 +#define SYSCAL_OPEN 2 +#define SYSCAL_CLOSE 3 +#define SYSCAL_WRITE 4 + +#endif diff --git a/kernel/src/process/include/syscallhandler.h b/kernel/src/process/include/syscallhandler.h new file mode 100644 index 00000000..95ca3380 --- /dev/null +++ b/kernel/src/process/include/syscallhandler.h @@ -0,0 +1,8 @@ +#ifndef SYSCALLHANDLER_H +#define SYSCALLHANDLER_H + +#include + +void handle_syscall(size_t syscallnr, size_t param1, size_t param2, size_t param3, size_t param4); + +#endif diff --git a/kernel/src/process/include/thread.h b/kernel/src/process/include/thread.h new file mode 100644 index 00000000..e7b9c158 --- /dev/null +++ b/kernel/src/process/include/thread.h @@ -0,0 +1,25 @@ +#ifndef COURSE_OS_THREAD_H +#define COURSE_OS_THREAD_H + +#include "./process.h" +#include "./registers.h" + +typedef enum ThreadState { + Runnable, + Running, + Died, +} ThreadState; + +typedef struct Thread { + Registers registers; + Process * process; + ThreadState state; +} Thread; + +Thread * create_thread(void * entry, Process * process); +void load_thread(Thread * thread); +void store_thread(Thread * thread); +void free_thread(Thread * thread); +void set_registers(Thread * thread, Registers * registers); + +#endif // COURSE_OS_THREAD_H diff --git a/kernel/src/process/process.c b/kernel/src/process/process.c new file mode 100644 index 00000000..f1a25fc4 --- /dev/null +++ b/kernel/src/process/process.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * Create a new process. + */ +Process *create_process(Elf *elf, Process *parent) { + Process *process = kmalloc(sizeof(Process)); + + process->parent = parent; + process->priority = DEFAULT_PROCESS_PRIORITY; + process->vas = create_vas(); + process->threads = vpa_create(5); + + switch_to_vas(process->vas); + for(size_t i = 0; i < elf->program.file_size; i += PAGE_SIZE) { + allocate_page(process->vas, i, true); + } + + memcpy((void *) elf->program.mem_location, elf->binary + elf->program.file_offset, elf->program.file_size); + + // for(int i = 0; i < elf->sections->length; i++) { + // ElfSection *section = vpa_get(elf->sections, i); + + // if(memcmp(section->address, 0x00000000, 4) == 0) continue; + // } + + Thread *thread = create_thread(elf->entry, process); + vpa_push(process->threads, thread); + + return process; +} + +/** + * Free a process, and it's memory. + */ +void free_process(Process *process) { + free_vas(process->vas); + vpa_free(process->threads, (FreeFunc) free_thread); + + kfree(process); +} diff --git a/kernel/src/process/scheduler.c b/kernel/src/process/scheduler.c new file mode 100644 index 00000000..61607d69 --- /dev/null +++ b/kernel/src/process/scheduler.c @@ -0,0 +1,40 @@ +#include "./include/scheduler.h" + +#include +#include + +Scheduler * active_scheduler = NULL; + +Scheduler * create_scheduler() { + Scheduler * scheduler = kmalloc(sizeof(Scheduler)); + scheduler->current_thread = NULL; + + return scheduler; +} + +void enable_scheduler(Scheduler * scheduler) { + DEBUG("[SCHEDULER] Starting scheduler.."); + active_scheduler = scheduler; + schedule_task(scheduler); +} + +Scheduler * get_scheduler() { + return active_scheduler; +} + +void schedule_task(Scheduler * scheduler) { + TRACE("[SCHEDULER] Scheduling a new thread.."); + load_thread(scheduler->current_thread); +} + +void add_process_to_scheduler(Scheduler * scheduler, Process * process) { + scheduler->current_thread = vpa_get(process->threads, 0); +} + +Thread * get_thread(Scheduler * scheduler) { + return scheduler->current_thread; +} + +void free_scheduler(Scheduler * scheduler) { + kfree(scheduler); +} diff --git a/kernel/src/process/syscallhandler.c b/kernel/src/process/syscallhandler.c new file mode 100644 index 00000000..3a5c4e24 --- /dev/null +++ b/kernel/src/process/syscallhandler.c @@ -0,0 +1,12 @@ +#include +#include +#include + +void handle_syscall(size_t syscallnr, size_t param1, size_t param2, size_t param3, size_t param4) { + INFO("Handling syscall %i", syscallnr); + + // switch (syscallnr) { + // case + // + // } +} diff --git a/kernel/src/process/test/process_test.c b/kernel/src/process/test/process_test.c new file mode 100644 index 00000000..f787e874 --- /dev/null +++ b/kernel/src/process/test/process_test.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +TEST_CREATE(test_process_smoke, { + Process *process = create_process((void *) 63, NULL); + + ASSERT_EQ(process->priority, DEFAULT_PROCESS_PRIORITY); + ASSERT_NOT_NULL(process->vas); + ASSERT_NOT_NULL(vpa_get(process->threads, 0)); + ASSERT_EQ(vpa_get(process->threads, 1), NULL); + + Thread *thread = vpa_get(process->threads, 0); + ASSERT_EQ(thread->registers.PC, 63); + ASSERT_EQ(thread->process, process); + + free_process(process); +}); diff --git a/kernel/src/process/test/scheduler_test.c b/kernel/src/process/test/scheduler_test.c new file mode 100644 index 00000000..a654cf7c --- /dev/null +++ b/kernel/src/process/test/scheduler_test.c @@ -0,0 +1,9 @@ +#include +#include +#include + +TEST_CREATE(test_scheduler_smoke, { + Scheduler *scheduler = create_scheduler(); + + free_scheduler(scheduler); +}); diff --git a/kernel/src/process/test/thread_test.c b/kernel/src/process/test/thread_test.c new file mode 100644 index 00000000..d6904eba --- /dev/null +++ b/kernel/src/process/test/thread_test.c @@ -0,0 +1,13 @@ +#include +#include +#include + +TEST_CREATE(test_thread_smoke, { + Thread *thread = create_thread((void *) 42, NULL); + + ASSERT_EQ(thread->state, Runnable); + ASSERT_EQ(thread->registers.PC, 42); + ASSERT_NEQ(thread->registers.SP, 0); + + free_thread(thread); +}); diff --git a/kernel/src/process/thread.c b/kernel/src/process/thread.c new file mode 100644 index 00000000..cbfe7933 --- /dev/null +++ b/kernel/src/process/thread.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include + +/** + * Create a new thread. + */ +Thread * create_thread(void * entry, Process * process) { + Thread * thread = kmalloc(sizeof(Thread)); + + thread->process = process; + thread->state = Runnable; + thread->registers = (struct Registers){0}; + + // Allocate stack. + size_t stack_end = 0x80000000 - (PAGE_SIZE * thread->process->threads->length); + allocate_page(thread->process->vas, stack_end - PAGE_SIZE, false); + thread->registers.SP = stack_end - 1; + + // Set instruction pointer. + thread->registers.PC = (size_t)entry; + thread->registers.CPSR = 0x16; + + // TODO: this makes returning from the thread main routine exit the thread + // thread->registers.LR = exit; + + return thread; +} + +/** + * Load a thread, and start executing. + * Will never return. + */ +void load_thread(Thread * thread) { + switch_to_vas(thread->process->vas); + switch_context(&thread->registers); + + __builtin_unreachable(); +} + +/** + * Overide the registers. + */ +void set_registers(Thread * thread, Registers * registers) { + memcpy(&thread->registers, registers, 17 * 4); +} + +/** + * Free the thread. + */ +void free_thread(Thread * thread) { + kfree((void *)thread->registers.SP); + kfree(thread); +} diff --git a/kernel/src/test/README.md b/kernel/src/test/README.md new file mode 100644 index 00000000..38691668 --- /dev/null +++ b/kernel/src/test/README.md @@ -0,0 +1,55 @@ +# Course OS Testing framework + +This directory is a custom-build testing framework by [Jonathan Dönszelmann](https://github.com/jonay2000/) and [Victor Roest](https://github.com/nullx76/). +To run tests, run + +```bash +make test +``` + + +## Creating tests. + +To create a new test, you can use the `TEST_CREATE` macro. It takes two arguments, a test name (which must be globally unique) and a block of code. +An example test would be + +```c +#include + +TEST_CREATE(test_one_plus_one, { + ASSERT_EQ(1 + 1, 2); +}) + +``` + +Tests created like this will be automatically detected and compiled into a file `src/test/test.c` which will then be compiled by gcc into the kernel. +Tests can be created in any file in any subdirectory of the src file. Tests will be randomized in order, and you cannot depend on the order in which tests are executed. +This has been done deliberately since we have had many problems with accidentally depending on this. + +When the MEM_DEBUG definition is given in the makefile (default for tests), the testing framework will record the allocator's number of bytes allocated before the test. If this number is not equal after the test, the test will fail. +When running with ENABLE_TESTS on, WARN macros will report file and line number, and DATA_ABORT handlers will panic and fail the test. + +## Assert macros + +There are a number of assertion macros included in `test.h`. + +They are listed here: + +| Macro name | usage | +| --- | --- | +| PASS() | Will immediately return and pass the test | +| FAIL() | Will immediately return and fail the test | +| ASSERT(expr) | Will fail the test if `expr` evaluates to zero/false | +| ASSERT_EQ(l, r) | Will fail the test if `l != r` | +| ASSERT_GT(l, r) | Will fail the test if `!(l >= r)` | +| ASSERT_GTEQ(l, r) | Will fail the test if `!(l > r)` | +| ASSERT_GT(l, r) | Will fail the test if `!(l >= r)` | +| ASSERT_LT(l, r) | Will fail the test if `!(l < r)` | +| ASSERT_LTEQ(l, r) | Will fail the test if `!(l <= r)` | +| ASSERT_NEQ(l, r) | Will fail the test if `l == r` | +| ASSERT_NOT_NULL(expr) | Will fail the test if `expr` evaluates to NULL | +| ASSERT_NULL(expr) | Will fail the test if `expr` doesn't evaluates to NULL | + + + + diff --git a/kernel/src/test/generate_tests.sh b/kernel/src/test/generate_tests.sh new file mode 100755 index 00000000..53ad8564 --- /dev/null +++ b/kernel/src/test/generate_tests.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# this bash script will read all directories to find tests. +# it will make a list of tests and write this to test.c +# the makefile will run this file automatically while building, +# so all tests are automatically executed. + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +# clear the file +echo -n "" > "$DIR/test.c" + +echo " +// DO NOT EDIT +// this file is generated by generate_tests.sh + +#ifdef ENABLE_TESTS + +#include +#include +#include + +size_t global_counter = 0; + +" >> "$DIR/test.c" + +#TESTFNS=$(grep -hr --include "*.c" -oP "(?<=TEST_CREATE\()(.*)(?=,)") +TESTFNS=$(grep -hr --include "*.c" -vP "^\s*\/\/.+" | grep -oP "(?<=TEST_CREATE\()(.*)(?=,)" | sort -R) + +for FNNAME in $TESTFNS +do + echo "int test_$FNNAME();" >> "$DIR/test.c" +done + +echo "void test_main(){" >> "$DIR/test.c" + +len=0 +for FNNAME in $TESTFNS +do + echo " if (!test_$FNNAME()) {return;}" >> "$DIR/test.c" + ((len++)) +done + + +# shellcheck disable=SC2028 +echo " + kprintf(\"TESTS COMPLETE. Passed %i tests\n\", $len); + SemihostingCall(ApplicationExit); +} +#endif +" >> "$DIR/test.c" diff --git a/kernel/src/test/include/test.h b/kernel/src/test/include/test.h new file mode 100644 index 00000000..1eac8a26 --- /dev/null +++ b/kernel/src/test/include/test.h @@ -0,0 +1,158 @@ + +#ifndef TEST_H +#define TEST_H + +#define TEST_PASS 1 +#define TEST_FAIL 0 + +#include +#include +#include + +// Only compile test definitions if enabled +#ifdef ENABLE_TESTS + +size_t global_counter; + + #define DEBUG_COUNT kprintf("[DEBUG COUNT] %s:%i %i\n", __FILE__, __LINE__, global_counter++); + + #ifdef MEM_DEBUG + #define TEST_CREATE(name, block) \ + int __internal_test_##name() { \ + heap_t * heap = mem_get_allocator(); \ + isize_t nbytes = heap->bytes_allocated; \ + block; \ + if (nbytes != (isize_t)heap->bytes_allocated) { \ + kprintf("\e[38;5;160mFAILED (MEMORY LEAK: %i bytes)\e[0m\n", \ + heap->bytes_allocated - nbytes); \ + return TEST_FAIL; \ + } \ + return TEST_PASS; \ + } \ + int test_##name() { \ + kprintf("\e[38;5;163m[TEST]\e[0m %s\n", #name); \ + int res = __internal_test_##name(); \ + if (res == TEST_PASS) { \ + kprintf("└─\e[92mPASSED\e[0m\n", #name); \ + return 1; \ + } else { \ + kprintf("└─\e[38;5;160mFAILED\e[0m\n", #name); \ + return 0; \ + } \ + } + #else + #define TEST_CREATE(name, block) \ + int __internal_test_##name() { \ + block; \ + return TEST_PASS; \ + } \ + int test_##name() { \ + kprintf("\e[38;5;163m[TEST]\e[0m %s\n", #name); \ + int res = __internal_test_##name(); \ + if (res == TEST_PASS) { \ + kprintf("└─\e[92mPASSED\e[0m\n"); \ + return 1; \ + } else { \ + kprintf("└─\e[38;5;160mFAILED\e[0m\n"); \ + return 0; \ + } \ + } + #endif + + #define PASS() return TEST_PASS + #define FAIL() return TEST_FAIL + #define ASSERT(expr) \ + do { \ + if (!expr) { \ + kprintf("failed assertion: %s:%i at ASSERT(%s)\n", __FILE__, __LINE__, #expr); \ + return TEST_FAIL; \ + } \ + } while (0) + #define ASSERT_EQ(l, r) \ + do { \ + if (l != r) { \ + kprintf( \ + "failed assertion: %s:%i at ASSERT_EQ(%s, %s)\n", __FILE__, __LINE__, #l, #r); \ + return TEST_FAIL; \ + } \ + } while (0) + #define ASSERT_GT(l, r) \ + do { \ + if (l <= r) { \ + kprintf( \ + "failed assertion: %s:%i at ASSERT_GT(%s, %s)\n", __FILE__, __LINE__, #l, #r); \ + return TEST_FAIL; \ + } \ + } while (0) + #define ASSERT_GTEQ(l, r) \ + do { \ + if (l < r) { \ + kprintf("failed assertion: %s:%i at ASSERT_GTEQ(%s, %s)\n", \ + __FILE__, \ + __LINE__, \ + #l, \ + #r); \ + return TEST_FAIL; \ + } \ + } while (0) + #define ASSERT_LT(l, r) \ + do { \ + if (l >= r) { \ + kprintf( \ + "failed assertion: %s:%i at ASSERT_LT(%s, %s)\n", __FILE__, __LINE__, #l, #r); \ + return TEST_FAIL; \ + } \ + } while (0) + #define ASSERT_LTEQ(l, r) \ + do { \ + if (l > r) { \ + kprintf("failed assertion: %s:%i at ASSERT_LTEQ(%s, %s)\n", \ + __FILE__, \ + __LINE__, \ + #l, \ + #r); \ + return TEST_FAIL; \ + } \ + } while (0) + #define ASSERT_NEQ(l, r) \ + do { \ + if (l == r) { \ + kprintf("failed assertion: %s:%i at ASSERT_NEQ(%s, %s)\n", \ + __FILE__, \ + __LINE__, \ + #l, \ + #r); \ + return TEST_FAIL; \ + } \ + } while (0) + #define ASSERT_NOT_NULL(e) \ + do { \ + if (e == NULL) { \ + kprintf( \ + "failed assertion: %s:%i\n at ASSERT_NOT_NULL(%s)\n", __FILE__, __LINE__, #e); \ + return TEST_FAIL; \ + } \ + } while (0) + #define ASSERT_NULL(e) \ + do { \ + if (e != NULL) { \ + kprintf("failed assertion: %s:%i\n at ASSERT_NULL(%s)\n", __FILE__, __LINE__, #e); \ + return TEST_FAIL; \ + } \ + } while (0) + +#else + + // If tests are disabled during compile time, all the macros expand to nothing + + #define TEST_CREATE(name, block) + #define PASS() 0 + #define FAIL() 0 + #define ASSERT(expr) 0 + #define ASSERT_EQ(l, r) d0 + +#endif + +void test_main(); + +#endif diff --git a/kernel/src/vm/README.md b/kernel/src/vm/README.md new file mode 100644 index 00000000..4924193a --- /dev/null +++ b/kernel/src/vm/README.md @@ -0,0 +1,55 @@ +# Virtual Memory + +## Description +The virtual memory implemention consists of the following parts: +* [ASID Allocator](include/asid_allocator.h) +* [Physical Memory Manager (PMM)](include/pmm.h) +* [Virtual Address Space Manager (VAS)](include/vas2.h) +* [Generic Virtual Memory Manager (VM)](include/vm2.h) + +### Initialization +The entry point for the virtual memory functionality is the [vm2_start()](vm2.c#L91) method. +It will first map all the physical to the 2 to 3GB region (only the first MiB of this was mapped by [startup.s](../common/startup.s)). +Afterwards it will remove the identity mapping done by that same file. After that is done the kernel is fully higher half. + +After mapping the physical memory it will initialize the PMM with the range of memory available, using the [pmm_int()](pmm.c#L17) function. +This function will then use the address space provided to build op all the structures needed for +physical page allocation. A general overview of how this is done and the methods available can be +found in its [header](include/pmm.h). + +And finally after the PMM has been initialized it will clear the pointer to the user pagetable (which was temporarily set); +flush the caches and return. + +## Memory map + +### Physical + +| Address | Description | +| ---------- | ---------------------------------------------------------------------- | +| 0x00000000 | Interrupt Vector Table | +| 0x00004000 | Kernel L1 page table | +| 0x00080000 | Kernel start | +| ... | *Kernel* | +| ... | *Kernel* | +| KERNEL END | Physical Memory Manager starting point | +| ... | Physical Memory Manager | +| 0xXXXXXXXX | End of Physical memory (Device dependent, max 1GB) | + +### Virtual + +| Address | Description | +| ---------- | ---------------------------------------------------------------------- | +| 0x00000000 | Virtual Process Address Space | +| 0x80000000 | (start of) remap of physical 0x00000000-0x40000000 | +| 0x80004000 | Kernel page table | +| 0x80008000 | Kernel start | +| ... | *Kernel* | +| ... | *Kernel* | +| KERNEL END | Location of the PMM in virtual address space | +| ... | (Virtual) Physical Memory Manager | +| 0xC0000000 | Kernel heap start (growing up) | +| 0xFFF00000 | MMIO mappings (growing down) | +| 0xFFFF0000 | High location of the vector table | + +***Note:*** Both the MMIO mapping and kernel heap occupy the same gigabyte. +The sum of the two can't exceed 1 gigabyte and when the kernel heap grows to touch the MMIO top, the heap is full. diff --git a/kernel/src/vm/asid_allocator.c b/kernel/src/vm/asid_allocator.c new file mode 100644 index 00000000..f70460d1 --- /dev/null +++ b/kernel/src/vm/asid_allocator.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +uint8_t curr = 0; +uint8_t allocated_ids[256] = {0}; + +bool tlb_everything_allocated = false; + +// TODO: Ensure atomicity +struct ASIDDescriptor asid_request_descriptor() { + uint8_t cache_iteration = ++(allocated_ids[curr]); + uint8_t tlb_cache_id = curr++; + + if (tlb_cache_id == 255) { tlb_everything_allocated = true; } + + struct ASIDDescriptor res = (struct ASIDDescriptor){ + .cache_iteration = cache_iteration, + .asid = tlb_cache_id, + }; + + return res; +} + +// TODO: Ensure atomicity +bool asid_check_and_update(struct ASIDDescriptor * desc) { + if (desc->cache_iteration != allocated_ids[desc->asid]) { + desc->cache_iteration = ++(allocated_ids[desc->asid]); + return true; + } + + return false; +} + +void asid_set(uint8_t id) { + DATA_SYNC_BARRIER() + + asm volatile("mrc p15, 0, r1, c13, c0, 1 \n" // Read Context ID (c13) register to R1 + "and r1, r1, #0xffffff00\n" + "orr r1, %0, r1\n" + "mcr p15, 0, r1, c13, c0, 1\n" // Write it back with the ASID set + ::"r"(id) + : "r1"); +} diff --git a/kernel/src/vm/include/asid_allocator.h b/kernel/src/vm/include/asid_allocator.h new file mode 100644 index 00000000..8ce110a1 --- /dev/null +++ b/kernel/src/vm/include/asid_allocator.h @@ -0,0 +1,65 @@ +#ifndef TLB_CACHE_ID_ALLOCATOR +#define TLB_CACHE_ID_ALLOCATOR + +#include +#include + +/// We have made a special allocator to keep track of all the ASIDs used and to determine if we +/// would need to flush the caches upon a context switch. This should greatly reduce the amount of +/// cache flushes needed and optimizes the usage of ASIDs. +/// +/// Designed by: +/// Victor Roest +/// +/// Implemented by: +/// Jonathan Donszelmann +/// Victor Roest + + +/// Terminology +/// * asid: Hardware process id used for the pagetable cache. +/// * cache_iteration: Which iteration of the cache we are on, determines if we should flush the +/// cache on a process switch or not. +/// * asid_descriptor: A pair of above two numbers. + +/// Each ASID Descriptor has 2 fields: +/// asid: the actual ASID used for this process. +/// cache_iteration: On which iteration of the cache we are (used to determine if a cache flush is +/// needed). +struct ASIDDescriptor { + uint8_t asid; + uint8_t cache_iteration; +}; + +/// Is set to true whenever all tlb_cache_ids are used up. +bool tlb_everything_allocated; + +/** + * Requests a tlb_descriptor. + * + * + * Allocates you a new tlb_id, + * if [tlb_everything_allocated] is true you should flush caches. + * If [tlb_everything_allocated] is false, you don't have to flush caches. + * @returns a TLBDescriptor + */ +struct ASIDDescriptor asid_request_descriptor(); + +/** + * Updates and checks a tlb_descriptor. + * + * It checks if your saved cache_iteration corresponds with the current one. + * If it doesn't it will update both, and return true. + * If it does it won't update and return false. + * @param desc the tlb_descriptor to check. + * @returns whether you should flush caches or not. + */ +bool asid_check_and_update(struct ASIDDescriptor * desc); + +/** + * Sets a specific ASID for the current core. + * @param id the ASID to set. + */ +void asid_set(uint8_t id); + +#endif diff --git a/kernel/src/vm/include/mmio.h b/kernel/src/vm/include/mmio.h new file mode 100644 index 00000000..6c39ec67 --- /dev/null +++ b/kernel/src/vm/include/mmio.h @@ -0,0 +1,17 @@ +#ifndef MMIO_H +#define MMIO_H + + +#define mmio_read(address) (*((volatile uint32_t *)(address))) +#define mmio_write(address, value) \ + mmio_write_internal((volatile uint32_t *)(address), (volatile uint32_t)(value)) + +// Do the mmio write in assembly to remove any chance of gcc optimizing the call away. *yes* even if +// it was marked volatile already. Hence the 4 hours it took us to make timer.c work...... +static inline void mmio_write_internal(volatile uint32_t * address, volatile uint32_t value) { + asm volatile("ldr r1, %1\n" + "str r1, %0\n" ::"m"(*address), + "m"(value)); +} + +#endif diff --git a/kernel/src/vm/include/pmm.h b/kernel/src/vm/include/pmm.h new file mode 100644 index 00000000..493c1a17 --- /dev/null +++ b/kernel/src/vm/include/pmm.h @@ -0,0 +1,203 @@ +/// This page allocator was completely designed and implemented by +/// Jonathan Donszelmann +/// Victor Roest +/// +/// ## Description +/// +/// It can allocate pages of sizes: +/// * 8KiB (L1 pagetables) +/// * 1KiB (L2 pagetables) +/// * 4KiB (Normal data pages) +/// All pages are aligned to their own size (i.e. The 8KiB pages are 8K algined) +/// +/// It stores all datastructures it uses in the same pages it allocates, +/// and can therefore be used without any existing allocator allocating it's space. +/// +/// This allocator has been made specifically for 32 bit ARM cpus. +/// This means it can *not* be used on x86 without adaptation. +/// It relies on addresses being 32 bits long and being aligned to boundaries to save (a lot) of +/// space. +/// +/// ## Overhead +/// Since this allocator also has to store some datastructures in itself, it obviously has some +/// overhead. This overhead is 16kb for every 512 pages of size 16kb allocated. For 64 bit systems +/// this ovehead would be larger. +/// +/// ## Time complexity +/// All operations performed on this allocator are O(1). They are in no way dependent on the size of +/// memory. With the exception of one method: The initialization of the allocator will loop once +/// through all of physical memory in increments of 16kb. +/// +/// ## Definitions +/// +/// In this code and the comments, we refer to the following things: +/// * (memory)slice A 16kb area of physical ram +/// * page A 4 kb area of physical ram (used for virtual user memory). +/// * sliceinfo A 12 byte element in the allocators datastructures, describing a single 16kb +/// block +/// * bucket A piece of memory that can be referred to by a single 16kb page full of +/// sliceinfo structs. +/// The size of a bucket is therefore 16kb * 682b which is just over 10.5 megabytes +/// * bucketinfo A slice containing an array of sliceinfo structs describing the contents of a +/// bucket. + +// TODO: Excluded regions. (for mmio for example) +// TODO: detect memory size. + +#ifndef PMM_H +#define PMM_H + +#include +#include + +#include "vm2.h" + + +/// The type of an 8KiB Slice +enum MemoryType { + L1PageTable, + L2PageTable, + Page, + BucketInfo, +}; + +/// A page with 4KiB of data. +struct Page { + uint8_t data[4096]; +}; + +// Early definition so we can have the cyclic dependency between MemorySliceInfo and MemorySlice. +union MemorySlice; + +/// A MemorySliceInfo contains all information for describing an 8KiB Slice of memory. +/// These are allocated inside so-called BucketInfo Slices. +struct MemorySliceInfo { + union { + uint32_t entry; + struct { + /// The type of the memory this SliceInfo is describing. + enum MemoryType type : 2; + + /// To determine how full this slice is if it describes a list of structures of less + /// than 8KiB. This is a BitVector where 1 means allocated and 0 means free. + uint32_t filled : 8; + + /// Unused bits + uint32_t unused : 22; + }; + }; + + /// Pointers used to build a linked list of SliceInfos + struct MemorySliceInfo * next; + struct MemorySliceInfo * prev; + + /// Pointer to the actual memory this SliceInfo is describing. + union MemorySlice * slice; +}; + + +#define SLICEINFO_PER_SLICE 512 // sizeof(union MemorySlice) / sizeof(struct MemorySliceInfo) +#define L2TABLES_PER_SLICE 8 // sizeof(union MemorySlice) / sizeof(struct L2PageTable) +#define PAGES_PER_SLICE 2 // sizeof(union MemorySlice) / sizeof(struct Page) + +/// A Memory slice of 8KB, that's also 8kb aligned. +/// A slice of 8kb can fit one of three things: +/// * 2 physical pages of 4kb +/// * 1 l1 pagetable of 8kb +/// * 8 l2 pagetabke of 1kb +/// * 512 MemorySliceInfo structs indexing other pages +union MemorySlice { + struct L1PageTable l1pt; + struct Page page[PAGES_PER_SLICE]; + struct L2PageTable l2pt[L2TABLES_PER_SLICE]; + // The sliceinfo array (bucketinfo) that contains the information of all Memoryslices in the + // next bucket. + struct MemorySliceInfo bucketinfo[SLICEINFO_PER_SLICE]; +}; + +/// The main data struct for the PhysicalMemoryManager (PMM). This struct gets created when calling +/// [pmm_init]. +struct PhysicalMemoryManager { + /// Two linked lists of unused and allocated slices, referred to by their SliceInfos. + struct MemorySliceInfo * unused; + struct MemorySliceInfo * allocated; + + /// The partially allocated entries, these can be linked lists or NULL. + struct MemorySliceInfo * l2ptPartialFree; + struct MemorySliceInfo * pagePartialFree; + + /// The start address of the region we are allowed to allocate in. + size_t start; + /// The end address of the region we are allowed to allocate in. + size_t end; +}; + +struct PhysicalMemoryManager physicalMemoryManager; + +// Allocator specific operations + +/** + * Initializes the PMM over the specified memory region. + * + * This functions will also set the global [physicalMemoryManager] variable. + * + * @param start of the memory region to be managed by the PMM + * @param end of the memory region to be managed by the pmm + */ +void pmm_init(size_t start, size_t end); + +/** + * Allocates a new MemorySliceInfo inside the PMM. + * For internal use only. + * @return a pointer to the allocated slice. + */ +struct MemorySliceInfo * pmm_new_sliceinfo_slice(); + +/** + * This function uses pointer arithmetic to determine the associated [MemorySliceInfo] for a + * [MemorySlice]. Despite the fact that we store the allocated pages in a linked list this function + * is O(1) due to aforementioned, pointer arithmetic. + * @param slice The slice to get the sliceinfo for. + * @return The [MemorySliceInfo] pointer for the given [MemorySlice]. + */ +struct MemorySliceInfo * pmm_get_sliceinfo_for_slice(union MemorySlice * slice); + + +/** + * Allocates an L1Pagetable. + * @return A pointer to said pagetable. + */ +struct L1PageTable * pmm_allocate_l1_pagetable(); + +/** + * Frees an L1Pagetable. + * @param pt The [struct L1PageTable] to free. + */ +void pmm_free_l1_pagetable(struct L1PageTable * pt); + +/** + * Allocates an L1Pagetable. + * @return A pointer to said pagetable. + */ +struct L2PageTable * pmm_allocate_l2_pagetable(); + +/** + * Frees an L2Pagetable. + * @param pt The [struct L2PageTable] to free. + */ +void pmm_free_l2_pagetable(struct L2PageTable * pt); + +/** + * Allocates a single 4KiB page. + * This is the function you want to use if you just want an area of memory. + * @return a pointer to the allocated [struct Page] + */ +struct Page * pmm_allocate_page(); + +/** + * Frees a single 4KiB Page. + * @param p The [struct Page] to free. + */ +void pmm_free_page(struct Page * p); + +#endif diff --git a/kernel/src/vm/include/vas2.h b/kernel/src/vm/include/vas2.h new file mode 100644 index 00000000..51f0569d --- /dev/null +++ b/kernel/src/vm/include/vas2.h @@ -0,0 +1,33 @@ +#ifndef VAS_2_H +#define VAS_2_H + +#include +#include +#include + +#define VAS2_INITIAL_PAGE_LIST_CAPACITY 10 + +struct vas2 { + struct ASIDDescriptor tlbDescriptor; + struct L1PageTable * l1PageTable; + VPArrayList * l2tables; + VPArrayList * pages; +}; + + +/// Creates a new virtual address spce for a process. +struct vas2 * create_vas(); + +/// Used in context switching. Sets up the mmu for a process to run. +void switch_to_vas(struct vas2 * vas); + +/// Freeing a vas clears all pagetables and pages associated with it. +/// It essentially frees all the memory a process has. +void free_vas(struct vas2 * vas); + +/// Creates a new page starting at the first page boundary below address. +/// This page is thus the page around the address. The address does not have to be +/// page boundary aligned. The new page is added to the vas and made executable if requested. +void allocate_page(struct vas2 * vas, size_t address, bool executable); + +#endif diff --git a/kernel/src/vm/include/vm2.h b/kernel/src/vm/include/vm2.h new file mode 100644 index 00000000..2f7522e2 --- /dev/null +++ b/kernel/src/vm/include/vm2.h @@ -0,0 +1,404 @@ +#ifndef VM_H +#define VM_H + +#include +#include +#include + + +/// Permissions for mapping a page +enum Access { + KernelRO, // kernel ro, user no access + KernelRW, // kernel rw, user no access + + // Everything below this is accessible for the kernel and the user. + + UserRO, // kernel rw, user ro + UserRW, // kernel rw, user rw +}; + +struct PagePermission { + enum Access access; // Access permissions for this page as specified above + bool executable; // If the Page should be executable or not +}; + +/// A L1PagetableEntry is an entry in the top level pagetable. +/// Relevant manual section: +/// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf +/// * 6.1 +/// * 6.5 (memory access control) +/// * 6.11.1 (entry layout) +/// * 6.13 (control registers) +/// * 6.10 (page faults and aborts) +typedef union L1PagetableEntry { + uint32_t entry; + /// A coarse l1pt entry means an l1pt entry that points to an l2pt. + /// The other possibility is a (super)section, where the l1pt maps a + /// far larger area of memory at once, without requiring an l2pt. + struct { + /// This 2 bit field gives what type of entry this is. + /// 00 for invalid pages (pagefault) + /// 01 for coarse pages (64kb). + /// 10 for sections and supersections. (see bit 18) + /// 11 for invalid pages (pagefault) + /// Note that for supersections you have to repeat this entry 16x to fill up all 1mb entries + /// that would lie within it, and the first of these 16 entries must be on a 16-word + /// boundary + uint32_t type : 2; + + /// Should be zero + uint32_t sbz1 : 1; + + /// Non-secure bit. This is used by the security extensions (TrustZone). + uint32_t nonSecure : 1; + + /// Should be zero + uint32_t sbz2 : 1; + + /// Domain. This is used by the security extensions (TrustZone). + uint32_t domain : 4; + + /// (P) ECC bit (some processors support this but the ARM1176 does *NOT*) + uint32_t ECC : 1; + + /// Top 22 bits of the base address. Points to a L2 pagetable. + /// formula: + /// base_address = (address >> 10); + uint32_t base_address : 22; + + } coarse; + + struct { + /// This 2 bit field gives what type of entry this is. + /// 00 for invalid pages (pagefault) + /// 01 for coarse pages (64kb). + /// 10 for sections and supersections. (see bit 18) + /// 11 for invalid pages (pagefault) + /// Note that for supersections you have to repeat this entry 16x to fill up all 1mb entries + /// that would lie within it, and the first of these 16 entries must be on a 16-word + /// boundary + uint32_t type : 2; + + /// If set, this page is bufferable + uint32_t bufferable : 1; + + /// If set, this page is cachable + uint32_t cachable : 1; + + /// Should be zero + uint32_t sbz2 : 1; + + /// Domain. This is used by the security extensions (TrustZone). + uint32_t domain : 4; + + /// (P) ECC bit (some processors support this but the ARM1176 does *NOT*) + uint32_t ECC : 1; + + /// Access permissions + /// accessExtended = 0: + /// Kernel: User: + /// 00 No access No access (Recommended) + /// 01 Read/Write No access + /// 10 Read/Write Read only + /// 11 Read/Write Read/Write + /// accessExtended = 1: + /// 00 Reserved Reserved + /// 01 Read only No access + /// 10 Read only Read only + /// 11 Read only Read only + uint32_t accessPermissions : 2; + + /// Type Extension + /// TEX C B Description Memory type Sharable + /// 000 0 0 Strongly ordered Strongly ordered yes + /// 000 0 1 Shared device Device yes 000 1 0 + /// Outer and Inner Write-Through,No Allocate on Write Normal Page + /// sharable if S bit is set 000 1 1 Outer and Inner Write-Back,No Allocate on Write + /// Normal Page sharable if S bit is set 001 0 0 Outer and Inner + /// Noncacheable Normal Page sharable if S bit is + /// set 001 0 1 Reserved 001 1 0 Reserved 001 1 1 Outer and Inner + /// Write-Back, Allocate on Write Normal Page sharable if S bit is + /// set 010 0 0 Non shared device Device no 010 0 + /// 1 Reserved 010 1 X Reserved 011 X X Reserved 1BB A A Cached Memory + /// Normal Page sharable if S bit is set + /// BB = Outer policy + /// AA = Inner policy + /// + /// BB *or* AA bits: + /// 00 Non-cachable + /// 01 Write-back cached, write allocate + /// 10 Write-through cached, no allocate on write + /// 11 Write-back cached, no allocate on write + /// + /// For more info (and there is a lot more!), see table 6-4 in the ARM1176jzf-s + /// [reference + /// manual](http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf) + uint32_t TEX : 3; + + /// Access extended bit. See `accessPermissions` + uint32_t accessExtended : 1; + + /// Marks the page sharable (see TEX). Also named S-bit + uint32_t sharable : 1; + + /// Not Global (ng). Determines how this is marked in the TLB. + uint32_t notglobal : 1; + + /// Supersection identifier is '1' if this entry is a supersection, is '0' if this is a + /// normal section + uint32_t supersection : 1; + + /// Non-secure bit. This is used by the security extensions (TrustZone). + uint32_t nonSecure : 1; + + /// Top 12 bits of the base address. Pointer to the first byte in a 1mb-large block. + /// If this entry refers to a supersection, the lower 4 bits Should Be Zero. + /// The top 8 bits now refer to a 16mb-large block + /// + /// formulae: + /// section_base_address = (address >> 20); + /// supersection_base_address = (address >> 24); + uint32_t base_address : 12; + } section; +} L1PagetableEntry; + +/// An L2PagetableEntry is an entry inside the L2Pagetable. +/// A single entry can address 4KiB of memory. +/// You shouldn't need to make any entries manually as you can use the [vm2_allocate_page] function +/// to allocate space for you. +typedef union L2PagetableEntry { + uint32_t entry; + struct { + /// This 2 bit field gives what type of entry this is. + /// 00 for invalid pages (pagefault) + /// 01 for large pages (64kb). + /// 10 for extended small pages (4kb) + /// 11 for extended *non-executable* small pages. (4kb) + /// Note that for large pages you have to repeat this entry 16x to fill up all 4kb entries + /// that would lie within it, and the first of these 16 entries must be on a 16-word + /// boundary + uint32_t type : 2; + + /// If set, this page is bufferable + uint32_t bufferable : 1; + + /// If set, this page is cachable + uint32_t cachable : 1; + + + /// Access permissions + /// accessExtended = 0: + /// Kernel: User: + /// 00 No access No access (Recommended) + /// 01 Read/Write No access + /// 10 Read/Write Read only + /// 11 Read/Write Read/Write + /// accessExtended = 1: + /// 00 Reserved Reserved + /// 01 Read only No access + /// 10 Read only Read only + /// 11 Read only Read only + uint32_t accessPermissions : 2; + + /// reserved (and Should Be Zero) + uint32_t shouldBeZero1 : 3; + + /// Access extended bit. See `accessPermissions` + uint32_t accessExtended : 1; + + /// Marks the page sharable (see TEX). Also named S-bit + uint32_t sharable : 1; + + /// Not Global (ng). Determines how this is marked in the TLB. + uint32_t notglobal : 1; + + /// Type Extension + /// For explanation: see [L1PagetableEntry.section.TEX] + uint32_t TEX : 3; + + /// Mark this page as non executable. + uint32_t nonExecutable : 1; + + /// Top 16 bits of the base address. Pointer to the first byte in a 64kb-large block. + /// formula: + /// base_address = (address >> 16); + uint32_t base_address : 16; + } __attribute__((packed)) largepage; + + struct { + /// This 2 bit field gives what type of entry this is. + /// 0 for invalid pages (pagefault) + /// 1 for large pages (64kb). + /// 2 for extended small pages (4kb) + /// 3 for extended *non-executable* small pages. (4kb) + /// Note that for large pages you have to repeat this entry 16x to fill up all 4kb entries + /// that would lie within it, and the first of these 16 entries must be on a 16-word + /// boundary + uint32_t type : 2; + + /// If set, this page is bufferable (B) + uint32_t bufferable : 1; + + /// If set, this page is cachable (S) + uint32_t cachable : 1; + + + /// Access permissions + /// accessExtended = 0: + /// Kernel: User: + /// 00 No access No access (Recommended) + /// 01 Read/Write No access + /// 10 Read/Write Read only + /// 11 Read/Write Read/Write + /// accessExtended = 1: + /// 00 Reserved Reserved + /// 01 Read only No access + /// 10 Read only Read only + /// 11 Read only Read only + uint32_t accessPermissions : 2; + + /// Type Extension + /// For explanation: see [L2PagetableEntry.largepage.TEX] + uint32_t TEX : 3; + + /// Access extended bit. See `accessPermissions` (APX) + uint32_t accessExtended : 1; + + /// Marks the page sharable (see TEX). Also named S-bit + uint32_t sharable : 1; + + /// Not Global (ng). Determines how this is marked in the TLB. + uint32_t notglobal : 1; + + /// Top 20 bits of the base address. Pointer to the first byte in a 4kb-large block. + /// formula: + /// base_address = (address >> 12); + uint32_t base_address : 20; + + } __attribute__((packed)) smallpage; +} L2PagetableEntry; + +/// The representation of an L1Pagetable +struct L1PageTable { + L1PagetableEntry entries[0x800]; +}; + +/// The representation of an L1Pagetable +struct L2PageTable { + L2PagetableEntry entries[0x100]; +}; + +/// Should be called early, initializes everything vm2 needs +void vm2_start(); + +/// Takes an L1PageTableEntry containing a physical address (in .*.base_address) and maps it to a +/// physical addres. The `bool remap` can be set to true and then this will overwrite whatever was +/// previously mapped at this virtual address in the pagetable. Will return if it did replace +/// something. Generally remap should be set to false, and the kernel should panic when this happen. +/// It usually indicates something went terribly enormously incredibly really really *really* wrong. +bool vm2_l1_map_physical_to_virtual(struct L1PageTable * pt, + union L1PagetableEntry entry, + size_t virtual, + bool remap); + +/// Peripheral mappings +/// Request a section of n megabytes virtual memory which is mapped to a physical section of ram of +/// the same n megabytes in which some mmio is located. Returns the virtual address. +size_t vm2_map_peripheral(size_t physical, size_t n_mebibytes); + +/// Maps a new 4KiB page at a virtual address. Returns a reference to this +/// page or NULL if unsuccessful. The physical location of this page is determined by the +/// [PMM](pmm.c). Since this allocates a 4KiB page, it has to go through L2Pagetables. It will +/// create the right L2 pagetables as it needs. You can make the allocated page executable with the +/// second to last parameter. If you want to keep track of your allocated L2Pagetables you can pass +/// a double pointer to `created_l2pt` And the function will return the pointer to the allocated +/// L2Pagetable in there (or NULL if no allocation happened). +void * vm2_allocate_page(struct L1PageTable * l1pt, + size_t virtual, + bool remap, + struct PagePermission perms, + struct L2PageTable ** created_l2pt); + +/// Frees a 4KiB page at a virtual address. The address does not need to be aligned. If the address +/// is not aligned, the aligned 4KiB page the address lies in is freed. +/// TODO: Does not yet free l2 pagetables when they become empty after enough pages are freed. For +/// TODO: processes this is never necessary as their pagetables are freed whenever the process +/// stops. For +/// TODO: the kernel it might be necessary. +/// Automatically unmaps the page from the l1pt it was in. +void vm2_free_page(struct L1PageTable * l1pt, size_t virtual); + +/// Should be called after updating a pagetable. +void vm2_flush_caches(); + +/// Flushes the caches associated with an ASID. +void vm2_flush_caches_of_ASID(uint8_t id); + +/// Enables a given l1 pagetable on the MMU. +void vm2_set_user_pagetable(struct L1PageTable * l1); + +/// The kernel's L1 Pagetable. +struct L1PageTable * kernell1PageTable; + +/// From the `kernel.ld` linker file. These are not arrays but this is how you refer to the pointers +/// by the linker script. +extern const size_t __KERNEL_BASE[]; +extern const size_t __KERNEL_TOP[]; +extern const size_t __KERNEL_VIRTUAL_OFFSET[]; + +/// Above 2Gigs is the virtual kernel area, this also includes all Virtual Memory constructs, and +/// the kernel stack. +#define KERNEL_VIRTUAL_OFFSET ((size_t)__KERNEL_VIRTUAL_OFFSET) + +#define PHYS2VIRT(address) ((size_t)(address) + KERNEL_VIRTUAL_OFFSET) +#define VIRT2PHYS(address) ((size_t)(address)-KERNEL_VIRTUAL_OFFSET) + +/// Make the kernel start in virtual memory at 2GB +#define KERNEL_VIRTUAL_START ((size_t)__KERNEL_BASE) +#define KERNEL_VIRTUAL_END ((size_t)__KERNEL_TOP) + +/// Location of the Kernel's Physical Memory Manager's Info structs. Can grow to a max of 16MiB when +/// using 4GiB RAM. +#define KERNEL_PMM_BASE KERNEL_VIRTUAL_END +// TODO: This changes per chipset and we either need to detect that or +// TODO: (the actual solution) support excluded regions in the pmm +// If we write above this range (0x3f000000) on a bcm2836 we enter the peripheral +// DMA region and are thus setting all kinds of registers. This kills qemu :) +#define PMM_TOP (KERNEL_VIRTUAL_OFFSET + 0x3f000000) + +// Location of the vector table in memory table. +// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABIFJFG.html +#define HIGH_VECTOR_LOCATION 0xFFFF0000 + +/// From this address down, mmio devices are mapped in the kernel's virtual address space. +#define KERNEL_MMIO_BASE ((4 * Gibibyte) - (1 * Mebibyte)) + +/// Address space for the kernel heap, grows towards the mmio +#define KERNEL_HEAP_BASE (3 * Gibibyte) + +#define KERNEL_PHYSICAL_START (KERNEL_VIRTUAL_START - KERNEL_VIRTUAL_OFFSET) +#define KERNEL_PHYSICAL_END (KERNEL_VIRTUAL_END - KERNEL_VIRTUAL_OFFSET) + +/// The L1 pagetable starts at 0x4000 and is itself 0x4000 bytes long. (0x1000 entries of 4 bytes). +/// The kernel starts at 0x8000 which is exactly at the end of the pagetable. (What a coincidence +/// *gasp*) +#define PhysicalL1PagetableLocation 0x4000 +#define VirtualL1PagetableLocation (KERNEL_VIRTUAL_OFFSET + PhysicalL1PagetableLocation) + +#define PAGE_SIZE (4 * Kibibyte) + +/* + * general purpose useful macros + */ + +/// aligns an address to the *next* boundary of size n. +/// only works where n is a power of 2 +#define ALIGN(address, n) ((((size_t)(address) + (size_t)(n)-1) & ~((size_t)(n)-1))); + +/// The purpose of the Data Synchronization Barrier operation is to ensure that +/// all outstanding explicit memory transactions complete before any following instructions begin. +/// This ensures that data in memory is up to date before the processor executes any more +/// instructions. +#define DATA_SYNC_BARRIER() asm volatile("eor r0, r0, r0\nmcr p15, 0, r0, c7, c10, 4"); + +#endif diff --git a/kernel/src/vm/pmm.c b/kernel/src/vm/pmm.c new file mode 100644 index 00000000..96ed20ca --- /dev/null +++ b/kernel/src/vm/pmm.c @@ -0,0 +1,323 @@ +#include +#include +#include +#include + +/// Private functions +// Returns the index of the first zero from the LSB +size_t first_free(uint16_t); + +// MemorySliceInfo linked list helper functions. +void push_to_ll(struct MemorySliceInfo ** head, struct MemorySliceInfo * entry); +struct MemorySliceInfo * pop_from_ll(struct MemorySliceInfo ** head); +// It's important that for this function you give it the correct head. If it's not it may happen +// That the head you give it will be mixed up with the actual head of the list it was in. +void remove_element_ll(struct MemorySliceInfo ** head, struct MemorySliceInfo * entry); + +void pmm_init(size_t start, size_t end) { + INFO("Building pmm from 0x%x to 0x%x of size 0x%x", start, end, end - start); + + // Create the first sliceinfo at the start address + struct MemorySliceInfo * firstinfo = (struct MemorySliceInfo *)start; + // This start address is itself a memory slice + union MemorySlice * firstslice = (union MemorySlice *)firstinfo; + + // Make the first sliceinfo describe this first slice. + firstinfo->next = NULL; + firstinfo->prev = NULL; + // It's type is sliceinfo + firstinfo->type = BucketInfo; + // It points to the first slice + firstinfo->slice = firstslice; + // And there's one sliceinfo struct in it. This first one. + firstinfo->filled = 1; + + // Now make a pmm with one sliceinfo in the allocated array. + physicalMemoryManager = (struct PhysicalMemoryManager){ + .start = start, + .end = end, + .l2ptPartialFree = NULL, + .pagePartialFree = NULL, + .allocated = firstinfo, + .unused = NULL, + }; + + // the infoindex is 1 since we just allocated the 0th one above^^^ + size_t infoindex = 1; + union MemorySlice * currentslice = firstslice; + + + // Go through all memory and index it with sliceinfo structs. + // We start 1 Memoryslice after `start` because we already allocated the first one at the start + // of this function. + for (union MemorySlice * i = ((union MemorySlice *)start + 1); i < ((union MemorySlice *)end); + i++) { + struct MemorySliceInfo * currentsliceinfo = ¤tslice->bucketinfo[infoindex]; + + // make this sliceinfo struct point to the right slice + currentsliceinfo->slice = i; + + // Add the sliceinfo to the unused list + push_to_ll(&physicalMemoryManager.unused, currentsliceinfo); + + // continue to the next sliceinfo + infoindex++; + + if (infoindex >= SLICEINFO_PER_SLICE) { + // We can now do this as we already made at least one new sliceinfo struct on the unused + // list Which we can use for this. + currentslice = pmm_new_sliceinfo_slice()->slice; + infoindex = 0; + } + } +} + +struct MemorySliceInfo * pmm_new_sliceinfo_slice() { + // Take a slice from the unused list and the the next one to the top of unused. + struct MemorySliceInfo * sliceinfo = pop_from_ll(&physicalMemoryManager.unused); + + // Change it's type to typeinfo + sliceinfo->type = BucketInfo; + sliceinfo->filled = 0; + + // Add it to the allocated list + push_to_ll(&physicalMemoryManager.allocated, sliceinfo); + + + return sliceinfo; +} + +struct MemorySliceInfo * pmm_get_sliceinfo_for_slice(union MemorySlice * slice) { + const int bucketsize = (SLICEINFO_PER_SLICE * sizeof(union MemorySlice)); + + // Take the address of the slice and determine in which bucket it falls. + // each bucket is a sliceinfo struct describing a slice with sliceinfo structs in it. + // The buckets therefore describes (682 * 16K) blocks. + + size_t offset_from_allocator_start = (size_t)slice - physicalMemoryManager.start; + + // divide by blocksize + size_t bucketindex = (offset_from_allocator_start) / (bucketsize); + + // We need a small correction factor. Normally the bucketinfo + // slice for a bucket sits in the *last* slice of the previous bucket. + // However, for the first bucket, the bucketinfo slice is actually the + // *first* slice in the bucket + size_t correction = bucketindex == 0 ? 0 : 1; + + // Multiply by blocksize again (NOTE: this is so we round down! The division and multiplication + // DO NOT CANCEL OUT) Subtract two as the bucket is actually the last page of the previous + // bucket. + union MemorySlice * bucketinfo = + ((union MemorySlice *)(physicalMemoryManager.start + bucketindex * bucketsize)) - + correction; + + // The first non-information slice in a bucket is always the slice after the information slice. + // Except for the first bucket. + size_t first_address_in_bucket = (size_t)(bucketinfo + correction); + + // now calculate how many times 16kb we are away from this. + // first_address_in_bucket - offset_from_allocator_start + size_t index = ((size_t)slice - first_address_in_bucket) / sizeof(union MemorySlice); + + struct MemorySliceInfo * info = &bucketinfo->bucketinfo[index]; + + return info; +} + +void pmm_free_l1_pagetable(struct L1PageTable * pt) { + if (pt == NULL) { return; } + + struct MemorySliceInfo * sliceinfo = pmm_get_sliceinfo_for_slice((union MemorySlice *)pt); + + remove_element_ll(&physicalMemoryManager.allocated, sliceinfo); + + // now push it on the unused list. + push_to_ll(&physicalMemoryManager.unused, sliceinfo); + + // Since it's the first thing on the unused list, make prev null. + sliceinfo->prev = NULL; +} + +struct L1PageTable * pmm_allocate_l1_pagetable() { + if (physicalMemoryManager.unused == NULL) { return NULL; } + + // Take a slice from the unused list. + struct MemorySliceInfo * sliceinfo = pop_from_ll(&physicalMemoryManager.unused); + + // Change it's type to typeinfo + sliceinfo->type = L1PageTable; + + // Put it on the allocated stack + push_to_ll(&physicalMemoryManager.allocated, sliceinfo); + + // Pre-zero the L1PageTable + memset(&sliceinfo->slice->l1pt, 0, sizeof(struct L1PageTable)); + + return &sliceinfo->slice->l1pt; +} + +struct L2PageTable * pmm_allocate_l2_pagetable() { + // First test if there's a partial allocated l2 pagetable + if (physicalMemoryManager.l2ptPartialFree != NULL) { + struct MemorySliceInfo * sliceinfo = physicalMemoryManager.l2ptPartialFree; + + uint32_t index = first_free(sliceinfo->filled); + + struct L2PageTable * newl2pt = &sliceinfo->slice->l2pt[index]; + + sliceinfo->filled |= (1u << index); + + // If it is filled + if (sliceinfo->filled == 0xff) { + // Remove from the partial free list + // We can ignore the return value here as we already got it. + pop_from_ll(&physicalMemoryManager.l2ptPartialFree); + + // add to allocated list + push_to_ll(&physicalMemoryManager.allocated, sliceinfo); + } + + memset(newl2pt, 0, sizeof(struct L2PageTable)); + return newl2pt; + } else { + struct MemorySliceInfo * sliceinfo = pop_from_ll(&physicalMemoryManager.unused); + + // Change it's type to typeinfo + sliceinfo->type = L2PageTable; + sliceinfo->filled = 1; + + // Put it on the partially allocated list + push_to_ll(&physicalMemoryManager.l2ptPartialFree, sliceinfo); + + struct L2PageTable * newl2pt = &sliceinfo->slice->l2pt[0]; + memset(newl2pt, 0, sizeof(struct L2PageTable)); + return newl2pt; + } +} + +struct Page * pmm_allocate_page() { + // First test if there's a partial allocated page page + if (physicalMemoryManager.pagePartialFree != NULL) { + struct MemorySliceInfo * sliceinfo = physicalMemoryManager.pagePartialFree; + + uint32_t index = first_free(sliceinfo->filled); + + + struct Page * newpage = &sliceinfo->slice->page[index]; + + sliceinfo->filled |= (1u << index); + + // If it is filled (2 pages) + if (sliceinfo->filled == 0b11) { + // Remove from the partial free list + // We can ignore the return value here as we already got it. + pop_from_ll(&physicalMemoryManager.pagePartialFree); + + // add to allocated list + push_to_ll(&physicalMemoryManager.allocated, sliceinfo); + } + + memset(newpage, 0, sizeof(struct Page)); + return newpage; + } else { + struct MemorySliceInfo * sliceinfo = pop_from_ll(&physicalMemoryManager.unused); + + // Change it's type to typeinfo + sliceinfo->type = Page; + sliceinfo->filled = 0b0001; + + // Put it on the partially allocated list + push_to_ll(&physicalMemoryManager.pagePartialFree, sliceinfo); + + struct Page * newpage = &sliceinfo->slice->page[0]; + memset(newpage, 0, sizeof(struct Page)); + return newpage; + } +} + +void pmm_free_page(struct Page * p) { + // works cuz rounding (we think, might just work because random luck) + struct MemorySliceInfo * info = pmm_get_sliceinfo_for_slice((union MemorySlice *)p); + + if (info->filled == 0b11) { + remove_element_ll(&physicalMemoryManager.allocated, info); + } else { + remove_element_ll(&physicalMemoryManager.pagePartialFree, info); + } + + // compute which subelement we are + size_t offset_from_slice_start = ((size_t)p - (size_t)info->slice); + size_t index_in_slice = offset_from_slice_start / sizeof(struct Page); + + // correctly clear the bit from filled + info->filled &= ~(1u << index_in_slice); + + // if there was only one l2pt in this slice, put it on unallocated + if (info->filled == 0x0) { + push_to_ll(&physicalMemoryManager.unused, info); + } else { + push_to_ll(&physicalMemoryManager.pagePartialFree, info); + } +} + +void pmm_free_l2_pagetable(struct L2PageTable * pt) { + // works cuz rounding (we think, might just work because random luck) + struct MemorySliceInfo * info = pmm_get_sliceinfo_for_slice((union MemorySlice *)pt); + + if (info->filled == 0xff) { + remove_element_ll(&physicalMemoryManager.allocated, info); + } else { + remove_element_ll(&physicalMemoryManager.l2ptPartialFree, info); + } + + // compute which subelement we are + size_t offset_from_slice_start = ((size_t)pt - (size_t)info->slice); + size_t index_in_slice = offset_from_slice_start / sizeof(struct L2PageTable); + + // correctly clear the bit from filled + info->filled &= ~(1u << index_in_slice); + + // if there was only one l2pt in this slice, put it on unallocated + if (info->filled == 00) { + push_to_ll(&physicalMemoryManager.unused, info); + } else { + push_to_ll(&physicalMemoryManager.l2ptPartialFree, info); + } +} + +void push_to_ll(struct MemorySliceInfo ** head, struct MemorySliceInfo * entry) { + if (*head != NULL) { (*head)->prev = entry; } + entry->next = *head; + *head = entry; +} + +struct MemorySliceInfo * pop_from_ll(struct MemorySliceInfo ** head) { + struct MemorySliceInfo * top = *head; + *head = (*head)->next; + if (*head != NULL) { (*head)->prev = NULL; } + + top->next = NULL; + top->prev = NULL; + + return top; +} + +void remove_element_ll(struct MemorySliceInfo ** head, struct MemorySliceInfo * entry) { + if (entry->next != NULL) { entry->next->prev = entry->prev; } + + if (entry->prev != NULL) { + entry->prev->next = entry->next; + } else { + *head = entry->next; + } + + entry->next = NULL; + entry->prev = NULL; +} + +size_t first_free(uint16_t filled) { + filled = ~filled; + // 32 because clz on arm counts from the 32nd aka most significant bit. + return 32u - __builtin_clz(filled & (uint16_t)(-filled)) - 1u; +} diff --git a/kernel/src/vm/test/test_asid.c b/kernel/src/vm/test/test_asid.c new file mode 100644 index 00000000..efe531e9 --- /dev/null +++ b/kernel/src/vm/test/test_asid.c @@ -0,0 +1,39 @@ +#include +#include + +TEST_CREATE(tlb_simple, { + struct ASIDDescriptor desc = asid_request_descriptor(); + + uint32_t id = desc.asid; + uint32_t iteration = desc.cache_iteration; + + if (asid_check_and_update(&desc)) { + ASSERT_NEQ(iteration, desc.cache_iteration); + } else { + ASSERT_EQ(iteration, desc.cache_iteration); + } + + ASSERT_EQ(id, desc.asid); +}) + +TEST_CREATE(tlb_intensive, { + // This tests asserts the properties of the TLBDescriptor in an extensive way, + // to ensure at least 1 overflow takes place + for (size_t i = 0; i < 666; i++) { + struct ASIDDescriptor desc = asid_request_descriptor(); + + uint32_t id = desc.asid; + uint32_t iteration = desc.cache_iteration; + + if (asid_check_and_update(&desc)) { + ASSERT_NEQ(iteration, desc.cache_iteration); + } else { + ASSERT_EQ(iteration, desc.cache_iteration); + } + + ASSERT_EQ(id, desc.asid); + } + + // Everything should have definitely been allocated by now. + ASSERT(tlb_everything_allocated); +}) diff --git a/kernel/src/vm/test/test_pagealloc2.c b/kernel/src/vm/test/test_pagealloc2.c new file mode 100644 index 00000000..301c8e0d --- /dev/null +++ b/kernel/src/vm/test/test_pagealloc2.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include + +// Warning: This method is O(n) and is thus quite slow on long lists. +size_t listlength(struct MemorySliceInfo * start) { + if (start == NULL) { return 0; } + + size_t count = 1; + for (; start->next != NULL; start = start->next) { count++; } + + return count; +} + +TEST_CREATE(test_pmm_constants, { + ASSERT_EQ(sizeof(struct MemorySliceInfo), 16); + ASSERT_EQ(sizeof(union MemorySlice) / sizeof(struct MemorySliceInfo), SLICEINFO_PER_SLICE); + ASSERT_EQ(sizeof(union MemorySlice) / sizeof(struct L1PageTable), 1); + ASSERT_EQ(sizeof(union MemorySlice) / sizeof(struct L2PageTable), L2TABLES_PER_SLICE); + ASSERT_EQ(sizeof(union MemorySlice) / sizeof(struct Page), PAGES_PER_SLICE); + ASSERT_EQ(sizeof(struct Page), PAGE_SIZE); +}) + +TEST_CREATE(test_allocate_pt, { + size_t unused = listlength(physicalMemoryManager.unused); + size_t allocated = listlength(physicalMemoryManager.allocated); + + struct L1PageTable * pt = pmm_allocate_l1_pagetable(); + + // Just try to overwrite everything a few times so if something breaks we'll hopefully see in + // the next tests. + memset(pt, 0, 1024 * 16); + memset(pt, 1, 1024 * 16); + + ASSERT_NOT_NULL(physicalMemoryManager.unused); + ASSERT_EQ(listlength(physicalMemoryManager.unused), unused - 1); + ASSERT_NOT_NULL(physicalMemoryManager.allocated); + ASSERT_EQ(listlength(physicalMemoryManager.allocated), allocated + 1); + + pmm_free_l1_pagetable(pt); + + ASSERT_EQ(listlength(physicalMemoryManager.unused), unused); + ASSERT_EQ(listlength(physicalMemoryManager.allocated), allocated); +}) + +TEST_CREATE(test_allocate_many_pt, { + size_t total = listlength(physicalMemoryManager.unused); + size_t totalallocated = listlength(physicalMemoryManager.allocated); + + const size_t amount = 520; + + struct L1PageTable * pages[amount]; + + for (size_t i = 0; i < amount; i++) { + pages[i] = pmm_allocate_l1_pagetable(); + ASSERT_NOT_NULL(pages[i]); + ASSERT_EQ(listlength(physicalMemoryManager.unused), total - (i + 1u)); + ASSERT_EQ(listlength(physicalMemoryManager.allocated), totalallocated + i + 1); + } + + struct L1PageTable * pt = pmm_allocate_l1_pagetable(); + + ASSERT_NOT_NULL(physicalMemoryManager.unused); + ASSERT_EQ(listlength(physicalMemoryManager.unused), total - (amount + 1)); + ASSERT_NOT_NULL(physicalMemoryManager.allocated); + + ASSERT_EQ(listlength(physicalMemoryManager.allocated), totalallocated + (amount + 1)); + + pmm_free_l1_pagetable(pt); + + + for (int i = 0; i < amount; i++) { pmm_free_l1_pagetable(pages[i]); } + + + ASSERT_NOT_NULL(physicalMemoryManager.unused); + ASSERT_EQ(listlength(physicalMemoryManager.unused), total); + ASSERT_EQ(listlength(physicalMemoryManager.allocated), totalallocated); +}) + +// Test the magic :sparkles: +TEST_CREATE(test_get_sliceinfo, { + struct L1PageTable * pt = pmm_allocate_l1_pagetable(); + + struct MemorySliceInfo * info = pmm_get_sliceinfo_for_slice((union MemorySlice *)pt); + + ASSERT_EQ(&info->slice->l1pt, pt); + + pmm_free_l1_pagetable(pt); +}) + +TEST_CREATE(test_doubly_linked_sliceinfo, { + struct MemorySliceInfo * curr = physicalMemoryManager.unused; + uint32_t length = listlength(curr); + + uint32_t i = 0; + do { + i++; + ASSERT_EQ(curr->next->prev, curr); + curr = curr->next; + } while (curr->next != NULL); + + ASSERT_EQ(i, length - 1); +}) + +// TODO: test_allocate_page +// TODO: test_allocate_l2pt + +size_t first_free(uint16_t filled); + +TEST_CREATE(test_first_free, { + ASSERT_EQ(first_free(0b000010), 0); + ASSERT_EQ(first_free(0b000011), 2); + ASSERT_EQ(first_free(0b000111), 3); + ASSERT_EQ(first_free(0b111101), 1); + ASSERT_EQ(first_free(0b111111), 6); +}) diff --git a/kernel/src/vm/test/test_vm2.c b/kernel/src/vm/test/test_vm2.c new file mode 100644 index 00000000..3dad2fe2 --- /dev/null +++ b/kernel/src/vm/test/test_vm2.c @@ -0,0 +1,7 @@ +#include +#include + +TEST_CREATE(test_size, { + ASSERT_EQ(sizeof(L2PagetableEntry), 4); + ASSERT_EQ(sizeof(L1PagetableEntry), 4); +}) diff --git a/kernel/src/vm/vas2.c b/kernel/src/vm/vas2.c new file mode 100644 index 00000000..b56f769f --- /dev/null +++ b/kernel/src/vm/vas2.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +/// FIXME: +/// WARNING: This code is untested, and quite hard to even make tests for. +/// This should just be used in a scheduler to see if it works. + +struct vas2 * create_vas() { + struct vas2 * newvas = kmalloc(sizeof(struct vas2)); + + *newvas = (struct vas2){ + .tlbDescriptor = asid_request_descriptor(), + .l1PageTable = pmm_allocate_l1_pagetable(), + .l2tables = vpa_create(VAS2_INITIAL_PAGE_LIST_CAPACITY), + .pages = vpa_create(VAS2_INITIAL_PAGE_LIST_CAPACITY), + }; + + return newvas; +} + +void switch_to_vas(struct vas2 * vas) { + if (asid_check_and_update(&vas->tlbDescriptor)) { + vm2_flush_caches_of_ASID(vas->tlbDescriptor.asid); + } + + asid_set(vas->tlbDescriptor.asid); + + vm2_set_user_pagetable((void *) VIRT2PHYS((size_t) vas->l1PageTable)); +} + +void free_vas(struct vas2 * vas) { + vpa_free(vas->l2tables, (FreeFunc)pmm_free_l2_pagetable); + vpa_free(vas->pages, (FreeFunc)pmm_free_page); + pmm_free_l1_pagetable(vas->l1PageTable); + kfree(vas); +} + +void allocate_page(struct vas2 * vas, size_t address, bool executable) { + struct PagePermission perms = (struct PagePermission){ + .executable = executable, + .access = UserRW, + }; + + struct L2PageTable * l2pt = NULL; + + void * page = vm2_allocate_page(vas->l1PageTable, address, false, perms, &l2pt); + + // TODO: L2pt is _always_ NULL + if (l2pt != NULL) { vpa_push(vas->l2tables, l2pt); } + + vpa_push(vas->pages, page); +} diff --git a/kernel/src/vm/vm2.c b/kernel/src/vm/vm2.c new file mode 100644 index 00000000..51ee7161 --- /dev/null +++ b/kernel/src/vm/vm2.c @@ -0,0 +1,271 @@ +#include +#include +#include +#include +#include +#include + +struct L1PageTable * kernell1PageTable = (struct L1PageTable *) + VirtualL1PagetableLocation; // NOLINT(cppcoreguidelines-interfaces-global-init) + // (defined in linker script) +bool mmu_started = false; + +static inline size_t l1pt_index(size_t address) { + return address >> 20u; +} + +static inline uint8_t l2pt_index(size_t address) { + return (address & 0x000ff000u) >> 12u; +} + +static inline size_t l1pt_base_address(size_t address) { + // For l1 they are the same + return l1pt_index(address); +} + +static inline size_t l2pt_base_address(size_t address) { + return address >> 12u; +} + +// Finds the location of an l2pt given an l1pt coarse entry. +static inline struct L2PageTable * find_l2pt(L1PagetableEntry * l1ptEntry) { + if (l1ptEntry->coarse.type == 1) { + return (struct L2PageTable *)PHYS2VIRT(l1ptEntry->coarse.base_address << 10u); + } else { + FATAL("Can't get L2 address from non-coarse L1 Entry"); + } +} + +bool vm2_l1_map_physical_to_virtual(struct L1PageTable * pt, + union L1PagetableEntry entry, + size_t virtual, + bool remap) { + bool remapped = false; + + if (pt->entries[l1pt_index(virtual)].entry != 0) { + if (remap) { + remapped = true; + TRACE("[MEM DEBUG] Remapping l1 page located at 0x%x", virtual); + } else { + // The entry is already mapped + FATAL("Request for already mapped address denied"); + } + } + + kernell1PageTable->entries[l1pt_index(virtual)] = entry; + + if (remap && remapped) { + // TODO: partial flush + vm2_flush_caches(); + } + + return remapped; +} + +void vm2_flush_caches() { + TRACE("[MEM DEBUG] Flushing caches"); + // TODO: Only a subset of these instructions are necessary + asm volatile("// invalidate caches\n" + "mcr p15, 0, %0, c7, c5, 0\n" + "// invalidate tlb\n" + "mcr p15, 0, %0, c8, c7, 0\n" + "// data sync barrier\n" + "mcr p15, 0, %0, c7,c10, 4\n" + + "mcr p15, 0, %0, c7, c10, 4\n" + "mcr p15, 0, %0, c7, c10, 5\n" + "mcr p15, 0, %0, c7, c14, 0\n" ::"r"(0x0)); +} + +// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf#page=219 +void vm2_flush_caches_of_ASID(uint8_t id) { + asm volatile("mcr p15, 0, %0, c8, c7, 2" // Invalidate TLB Entry on ASID Match + ::"r"(id)); +} + +void vm2_set_user_pagetable(struct L1PageTable * l1) { + // http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf#page=360 + asm volatile("MCR p15, 0, %0, c2, c0, 0\n" ::"r"(l1)); // Set Translation base address 0 +} + +// Starts the actual MMU after this function we live in Virtual Memory +void vm2_start() { + size_t available_RAM; + + switch (get_hardwareinfo()->boardType) { + case RaspberryPiZero: + available_RAM = 512 * Mebibyte; + break; + case RaspBerryPiTwo: + available_RAM = 1 * Gibibyte; + break; + default: + // TODO: memory detection? Or just not bother. + FATAL("Board type unsupported by VM2\n"); + } + + INFO("Using memory size 0x%x", available_RAM); + + /// Unmap the 1:1 mapped first megabyte which startup.s created to boot to a higher half kernel. + /// We don't need it anymore! + kernell1PageTable->entries[0] = (L1PagetableEntry){0}; + + /// Map the entire gigabyte (or less on some boards, but never more) physical ram to virtual + /// 2GB-3GB. this includes the kernel, kernel stack, kernel pagetables, process pagetables, pmm + /// etc. + for (size_t i = 0; i < (size_t)available_RAM; i += Mebibyte) { + vm2_l1_map_physical_to_virtual(kernell1PageTable, + (union L1PagetableEntry){ + .section.type = 2, + .section.accessPermissions = 1, + .section.base_address = l1pt_base_address(i), + }, + KERNEL_VIRTUAL_OFFSET + i, + true); + } + + pmm_init(KERNEL_PMM_BASE, PMM_TOP); + + vm2_set_user_pagetable(NULL); + + vm2_flush_caches(); + + mmu_started = true; +} + +void vm2_free_page(struct L1PageTable * l1pt, size_t virtual) { + // TODO: Maybe delete underlying L2? (It has bad time complexity for now, we don't). + + L1PagetableEntry * l1Entry = &l1pt->entries[l1pt_index(virtual)]; + if (l1Entry->section.type == 1) { + struct L2PageTable * l2 = find_l2pt(l1Entry); + union L2PagetableEntry * l2Entry = &l2->entries[l2pt_index(virtual)]; + + struct Page * page_address = + (struct Page *)VIRT2PHYS(l2Entry->smallpage.base_address << 12u); + pmm_free_page(page_address); + + l2Entry->entry = 0; + + // TODO: Partial cache flushes + vm2_flush_caches(); + } else { + WARN("Invalid section type, can't free non-page"); + } +} + +void * vm2_allocate_page(struct L1PageTable * l1pt, + size_t virtual, + bool remap, + struct PagePermission perms, + struct L2PageTable ** created_l2pt) { + L1PagetableEntry * l1Entry = &l1pt->entries[l1pt_index(virtual)]; + struct L2PageTable * l2 = NULL; + + switch (l1Entry->section.type) { + case 0:; + // Allocate coarse/l2 pagetable + l2 = pmm_allocate_l2_pagetable(); + *l1Entry = (L1PagetableEntry){ + .coarse = + { + .type = 1, + .base_address = ((size_t)VIRT2PHYS((size_t)l2)) >> 10u, + }, + }; + + // Return the allocated l2pt + if (created_l2pt != NULL) { + *created_l2pt = l2; + } + + /** Fallthrough **/ + case 1:; + struct Page * page = pmm_allocate_page(); + // There already is a coarse pagetable + if (l2 == NULL) { l2 = find_l2pt(l1Entry); } + union L2PagetableEntry * l2Entry = &l2->entries[l2pt_index(virtual)]; + + if (l2Entry->entry != 0 && !remap) { + FATAL("Overwriting entry in l2pt : 0x%x", virtual); + } else if (l2Entry->entry != 0 && remap) { + TRACE("[MEM DEBUG] Remapping l2 page located at 0x%x", virtual); + } + + // Set up perms correctly + int accessPerms = 0; + int accessExtended = 0; + bool global = false; + + switch (perms.access) { + case KernelRW: + accessPerms = 0b01; + accessExtended = 0; + global = true; + break; + case KernelRO: + accessPerms = 0b01; + accessExtended = 1; + global = true; + break; + case UserRO: + accessPerms = 0b10; + accessExtended = 0; + global = false; + break; + case UserRW: + accessPerms = 0b11; + accessExtended = 0; + global = false; + break; + default: + WARN("[MEM DEBUG] No access permissions specified, falling back to No access "); + break; + } + + *l2Entry = (union L2PagetableEntry){ + .smallpage = + { + .type = 2 + !perms.executable, + .bufferable = 0, + .cachable = 0, + .notglobal = !global, + .accessPermissions = accessPerms, + .accessExtended = accessExtended, + .base_address = l2pt_base_address(((size_t)VIRT2PHYS(page))), + }, + }; + + if (remap) { vm2_flush_caches(); } + + // make sure that if we didn't allocate a new pt, we set created_l2pt it to null + if (created_l2pt != NULL && *created_l2pt != NULL) { *created_l2pt = NULL; } + + return page; + default: + // This is a (super)section and we can't make it a coarse pagetable. Error. + WARN("[MEM DEBUG] L1 Entry is a section or super section, can't map a page there"); + return NULL; + } +} + +size_t vm2_map_peripheral(size_t physical, size_t n_mebibytes) { + static size_t mmio_current_top = KERNEL_MMIO_BASE; + + mmio_current_top -= (n_mebibytes * Mebibyte); + + for (size_t i = 0; i < n_mebibytes; i++) { + kernell1PageTable->entries[l1pt_index(mmio_current_top)] = (L1PagetableEntry){ + .section.type = 2, + .section.accessPermissions = 1, + .section.base_address = l1pt_base_address(physical), + }; + + mmio_current_top += Mebibyte; + physical += Mebibyte; + } + + mmio_current_top -= (n_mebibytes * Mebibyte); + + return mmio_current_top; +} diff --git a/kernel/stacks.s b/kernel/stacks.s deleted file mode 100644 index e0768994..00000000 --- a/kernel/stacks.s +++ /dev/null @@ -1,52 +0,0 @@ -.equ stack_size, 0x1000 -.equ stack_base, 0xfffff000 - -.equ Mode_USR, 0x10 -.equ Mode_FIQ, 0x11 -.equ Mode_IRQ, 0x12 -.equ Mode_SVC, 0x13 -.equ Mode_MON, 0x16 -.equ Mode_ABT, 0x17 -.equ Mode_UND, 0x1B -.equ Mode_SYS, 0x1F - - MOV R1, R0 // R0 has p_bootargs, which we need to hang onto - LDR R0, =stack_base - MSR CPSR_c, #Mode_FIQ - MOV sp, R0 - SUB R0, R0, #stack_size - - MSR CPSR_c, #Mode_IRQ - MOV sp, R0 - SUB R0, R0, #stack_size - - MSR CPSR_c, #Mode_SVC - MOV sp, R0 - SUB R0, R0, #stack_size - - MSR CPSR_c, #Mode_MON - MOV sp, R0 - SUB R0, R0, #stack_size - - MSR CPSR_c, #Mode_ABT - MOV sp, R0 - SUB R0, R0, #stack_size - - MSR CPSR_c, #Mode_UND - MOV sp, R0 - SUB R0, R0, #stack_size - - MSR CPSR_c, #Mode_SYS - MOV sp, R0 - - MSR CPSR_c, #Mode_SVC - ADD fp, sp, #0 - - EOR R0, R0 - ADD R0, pc, #0xf0000000 - MOV pc, R0 - - EOR R0, R0 - ADD R0, lr, #0xf0000000 - MOV lr, R0 - MOV R0, R1 diff --git a/kernel/start.c b/kernel/start.c deleted file mode 100644 index 39e960a9..00000000 --- a/kernel/start.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * A bit of background: - * - The ARM architecture has 7 modes of operation: - * + USR - user mode - * + FIQ - processing "fast" interrupts - * + IRQ - processing "normal" interrupts - * + SVC - proctected mode for OS - * + UND - processing an undefined instruction exception - * + SYS - also protecteed mode for OS --if anyone wants to clarify, feel free-- - * - * - These modes can be entered or exited by modifying the CPSR (status register), first 5 bits - * + 0b10000 = user mode - * + 0b10001 = FIQ (fast interrupt) mode - * + 0b10010 = IRQ (normal interrupt) mode - * + 0b10011 = SVC (supervisor, or, OS) mode - * (others...) - */ - -#include -#include "hw_handlers.h" -#include "global_defs.h" -#include "argparse.h" -#include "interrupt.h" -#include "mmap.h" -#include "process.h" -#include "memory.h" -#include "drivers/uart.h" -#include "drivers/mmci.h" -#include "klibc.h" -#include "vm.h" -#include "fs/open_table.h" //to initialize fs opentable -#include "mem_alloc.h" -#include "tests.h" -#include "drivers/timer.h" -#include "kthread.h" -#include "scheduler.h" - -// Tests -#include "tests/test_klibc.h" -#include "tests/test_hash_map.h" -#include "tests/test_mem_alloc.h" -#include "tests/test_vm.h" -#include "tests/test_priority_queue.h" - -#define UART0_IMSC (*((volatile uint32_t *)(UART0_ADDRESS + 0x038))) - -void uart_handler(void *null) -{ - print_uart0("uart0!\n"); -} - -// This start is what u-boot calls. It's just a wrapper around setting up the -// virtual memory for the kernel. -void start(uint32_t *p_bootargs) -{ - // Initialize the virtual memory - print_uart0("Enabling MMU...\n"); - vm_init(); - os_printf("Initialized VM datastructures.\n"); - mmap(p_bootargs); -} - - - -// This start is what starts the kernel. Note that virtual memory is enabled -// at this point (And running, also, in the kernel's VAS). -void start2(uint32_t *p_bootargs) -{ - // Setup all of the exception handlers... (hrm, interaction with VM?) - init_vector_table(); - - // Setup kmalloc... - init_heap(); - - //print_uart0("\nCourseOS!\n"); - - splash(); - - // Test stuff... - /*int *p = (int*)0xFFFFFFF0; - p[0] = 1; - os_printf("0x%x == 1?\n", p[0]);*/ - - //run_vm_tests(); - //INFO("There are %d free frames.\n", vm_count_free_frames()); - //run_mem_alloc_tests(); - //INFO("There are %d free frames.\n", vm_count_free_frames()); - //run_prq_tests(); - //run_hmap_tests(); - - kfs_init(0, 0, 0); - - - /* - 4-15-15: #Prakash: What happens if we let the program load here? - Let's make argparse_process() do its thing - - Note: As of 4-15-15 this fails horribly with hello.o not being - recognized as an ELF file and DATA ABORT HANDLER being syscalled - */ - - // enable interrupt handling - enable_interrupts(); - - // initialize the timers - initialize_timers(); - - //assert(1==2 && "Test assert please ignore"); - process_init(); - - sched_init(); - - // FIXME: temporary - os_printf("Programming the timer interrupt\n"); - start_timer_interrupts(0, 10); - - argparse_process(p_bootargs); - - print_uart0("done parsing atag list\n"); - - //init_kheap(31 * 0x100000); - //init_uheap(0x100000); - - //initialize pcb table and PID - /* init_all_processes(); */ - //print_process_state(0); - //run_process_tests(); - //print_PID(); - // init_q(); - //main(); - - - SLEEP; -} diff --git a/kernel/startup.s b/kernel/startup.s deleted file mode 100644 index d0d05445..00000000 --- a/kernel/startup.s +++ /dev/null @@ -1,9 +0,0 @@ -.global _Reset - -_Reset: - LDR sp, =stack_top - MOV R0, R2 - BL start -loop: - WFI - B loop diff --git a/kernel/tests.c b/kernel/tests.c deleted file mode 100644 index addc9729..00000000 --- a/kernel/tests.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "global_defs.h" -#include "tests.h" -#include "klibc.h" -#include "mem_alloc.h" - -//This function executes and displays results of test set given to it. -void run_tests(Test *tests[], int num_tests) -{ - int i; - for (i = 0; i < num_tests; i++) - { - os_printf("Running test: %s", tests[i]->test_name); - os_printf(" ... \n"); - //evaluates test here, if it passes prints PASSES else FAILS - if (!(tests[i]->testptr)()) - { - os_printf(":-D\n\n"); - } - else - { - os_printf("=(\n\n"); - } - } -} - -Test* create_test(char *name, int (*test_function)(void*)) -{ - Test *test = (Test*) kmalloc(sizeof(Test)); - test->test_name = name; - test->testptr = test_function; - return test; -} - -int test1() -{ - return TRUE; -} - -int test2() -{ - return FALSE; -} diff --git a/kernel/tests/Makefile b/kernel/tests/Makefile deleted file mode 100644 index 0006c0c7..00000000 --- a/kernel/tests/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -include $(CURDIR)/../../config.mk - -TOOLCHAIN_PATH:=$(CURDIR)/../../$(TOOLCHAIN_DIR)/$(BARE_METAL_TARGET)/bin -CC:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-gcc -INCL:=$(CURDIR)/../include/ -MAKE:=$(CURDIR)/../ -CFLAGS = -pipe -std=c99 -ffreestanding - -default: tests - -tests: test_vm.o test_hash_map.o test_mem_alloc.o test_priority_queue.o test_fs.o - $(MAKE)Makefile - $(CC) $(CFLAGS) -lc -o tests test_hash_map.o test_mem_alloc.o test_priority_queue.o test_vm.o test_fs.o - -test_fs.o: test_fs.c $(INCL)/tests.h $(INCL)/file.h ../fs/cmdline/file.h - $(CC) $(CFLAGS) -lc -o test_fs test_fs.c - -test_hash_map.o: test_hash_map.c $(INCL)/tests.h $(INCL)/tests/test_hash_map.h $(INCL)hash_map.h $(INCL)/klibc.h - $(CC) $(CFLAGS) -lc -o test_hash_map test_hash_map.c - -test_mem_alloc.o: test_mem_alloc.c $(INCL)/tests.h $(INCL)/tests/test_mem_alloc.h $(INCL)/klibc.h $(INCL)/vm.h - $(CC) $(CFLAGS) -lc -o test_mem_alloc test_mem_alloc.c - -test_priority_queue.o: test_priority_queue.c $(INCL)/tests.h $(INCL)/tests/test_priority_queue.h $(INCL)/priority_queue.h $(INCL)/klibc.h - $(CC) $(CFLAGS) -lc -o test_priority_queue test_priority_queue.c - -test_vm.o: test_vm.c $(INCL)/tests.h $(INCL)/klibc.h $(INCL)/memory.h $(INCL)/vm.h - $(CC) $(CFLAGS) -lc -o test_vm test_vm.c - -%.o: %.c - $(CC) $(CFLAGS) -c -mcpu=arm1176jzf-s $< -o $@ - -clean: - rm -f *.o - rm -f tests - rm -f test_fs - rm -f test_vm - rm -f test_hash_map - rm -f test_mem_alloc - rm -f test_priority_queue \ No newline at end of file diff --git a/kernel/tests/a.out b/kernel/tests/a.out deleted file mode 100755 index 6d219ccb..00000000 Binary files a/kernel/tests/a.out and /dev/null differ diff --git a/kernel/tests/test_fs.c b/kernel/tests/test_fs.c deleted file mode 100644 index 6230a4ea..00000000 --- a/kernel/tests/test_fs.c +++ /dev/null @@ -1,107 +0,0 @@ -#include "tests.h" -#include "klibc.h" -#include "fs/file.h" - - - -int test_fs_1() -{ - os_printf("\nCREATING /foo\n"); - int fd1 = kcreate("/foo", 'w', 1); - - os_printf("\nCREATING /bar\n"); - int fd2 = kcreate("/bar", 'w', 1); - - os_printf("\nCREATING /foo/baz.txt\n"); - int fd3 = kcreate("/foo/baz.txt", 'w', 0); - - os_printf("closing /foo/baz.txt \n"); - kclose(fd3); - - os_printf("\nnow opening file: /foo/baz.txt\n"); - int fd_new = kopen("/foo/baz.txt", 'w'); - os_printf("file descriptor is: %d\n", fd_new); - os_printf("closing /foo/baz.txt \n"); - kclose(fd_new); - - os_printf("\nnow opening file: /foo/baz.txt again to write to it\n"); - fd_new = kopen("/foo/baz.txt", 'w'); - char *s = "Hellooooooooooooooooooooooolllllllllllll world!!!"; - kwrite(fd_new, s, os_strlen(s)); - kclose(fd_new); - os_printf("closing /foo/baz.txt \n"); - - os_printf("\nnow opening file: /foo/baz.txt to read from it\n"); - fd_new = kopen("/foo/baz.txt", 'r'); - char buf[256]; - os_memset(&buf, 0, 256); - int nbytes = kread(fd_new, buf, 256); - os_printf("Read %d bytes from file.\n", nbytes); - os_printf("the buffer is: '%s'\n", buf); - kclose(fd_new); - kclose (fd1); - kclose (fd2); - kclose (fd3); - - return 0; -}//end test_fs_1() - -int test_fs_1_old() -{ - - return 0; -}//end test_fs1() - - - - -int test_fs_2() { - LOG("\nWriting a lot of data to /foobar2...\n"); - - int fd = kcreate("/foobar2", 'w', 0); - kclose(fd); - - // Okay, let's try making /foobar really big. - fd = kopen("/foobar2", 'w'); - int buf[256]; - int i; - for (i=0; i<256; i++) { - buf[i] = i*3; - } - // Write buf out 128 times -#define CNT 64 - for (i=0; iis_dir); - return 0; -} - -void run_fs_tests() { - Test *tests[1]; - tests[0] = create_test("test_fs_1", &test_fs_1); - //tests[1] = create_test("test_fs_2", &test_fs_2); - //run_tests(tests, 2); - // tests[1] = create_test("test_fs_2", &test_fs_2); - run_tests(tests, 1); -} diff --git a/kernel/tests/test_hash_map.c b/kernel/tests/test_hash_map.c deleted file mode 100644 index 9d76fda6..00000000 --- a/kernel/tests/test_hash_map.c +++ /dev/null @@ -1,187 +0,0 @@ -#include "tests.h" -#include "tests/test_hash_map.h" -#include "data_structures/hash_map.h" -#include "klibc.h" - -#define NUM_TESTS 4 - -#define new(a) ((a*) kmalloc(sizeof(a))) - -//This is where you define the tests you want to run. They return 1 on success and 0 on failure. - -//Tests the create function -int test_hmap_1() { - hmap_handle* hmap1 = hmap_create(); - hmap_handle* hmap2 = hmap_create_fixed(3); - - if (!hmap1) { - os_printf("expected value"); - return TEST_FAIL; - } - - if (!hmap2) { - os_printf("expected value"); - return TEST_FAIL; - } - - return TEST_OK; -} - -// Test put and get functions -int test_hmap_2() { - hmap_handle* hmap; - hmap = hmap_create(); - - int* data1; - int* data2; - int* data3; - - data1 = new(int); - *data1 = 0; - hmap_put(hmap, (long) (*data1), data1); - - data2 = new(int); - *data2 = 1; - hmap_put(hmap, (long) (*data2), data2); - - data3 = new(int); - *data3 = 2; - hmap_put(hmap, (long) (*data3), data3); - - if (hmap_get(hmap, (long) (*data1)) != data1 - || hmap_get(hmap, (long) (*data2)) != data2 - || hmap_get(hmap, (long) (*data3)) != data3) { - kfree(data1); - kfree(data2); - kfree(data3); - hmap_free(hmap); - return TEST_FAIL; - } - - return TEST_OK; -} - -// Test remove function -int test_hmap_3() { - hmap_handle* hmap; - hmap = hmap_create(); - - int* data1; - int* data2; - int* data3; - - data1 = new(int); - *data1 = 0; - hmap_put(hmap, (long) (*data1), data1); - - data2 = new(int); - *data2 = 1; - hmap_put(hmap, (long) (*data2), data2); - - data3 = new(int); - *data3 = 2; - hmap_put(hmap, (long) (*data3), data3); - - int* tmp1 = hmap_remove(hmap, (long) (*data1)); - int* tmp2 = hmap_remove(hmap, (long) (*data2)); - int* tmp3 = hmap_remove(hmap, (long) (*data3)); - - if (tmp1 != data1 || tmp2 != data2 || tmp3 != data3 - || hmap_count(hmap) != 0) { - kfree(tmp1); - kfree(tmp2); - kfree(tmp3); - hmap_free(hmap); - return TEST_FAIL; - } - - kfree(tmp1); - kfree(tmp2); - kfree(tmp3); - hmap_free(hmap); - return TEST_OK; -} - -// Test count function -int test_hmap_4() { - hmap_handle* hmap; - hmap = hmap_create(); - - int* data1; - int* data2; - int* data3; - int* data4; - - data1 = new(int); - *data1 = 0; - hmap_put(hmap, (long) (*data1), data1); - - if (hmap_count(hmap) != 1) { - kfree(data1); - hmap_free(hmap); - return TEST_FAIL; - } - - data2 = new(int); - *data2 = 1; - hmap_put(hmap, (long) (*data2), data2); - - if (hmap_count(hmap) != 2) { - kfree(data1); - kfree(data2); - hmap_free(hmap); - return TEST_FAIL; - } - - data3 = new(int); - *data3 = 2; - hmap_put(hmap, (long) (*data3), data3); - - if (hmap_count(hmap) != 3) { - kfree(data1); - kfree(data2); - kfree(data3); - hmap_free(hmap); - return TEST_FAIL; - } - - kfree(hmap_remove(hmap, (long) (*data2))); - - if (hmap_count(hmap) != 2) { - kfree(data1); - kfree(data3); - hmap_free(hmap); - return TEST_FAIL; - } - - data4 = new(int); - *data4 = 3; - hmap_put(hmap, (long) (*data4), data4); - - if (hmap_count(hmap) != 3) { - kfree(data1); - kfree(data3); - kfree(data4); - hmap_free(hmap); - return TEST_FAIL; - } - - kfree(data1); - kfree(data2); - kfree(data3); - kfree(data4); - hmap_free(hmap); - return TEST_OK; -} - -//function running tests -void run_hmap_tests() { - Test *tests[NUM_TESTS]; - tests[0] = create_test("test_hmap_1", &test_hmap_1); - tests[1] = create_test("test_hmap_2", &test_hmap_2); - tests[2] = create_test("test_hmap_3", &test_hmap_3); - tests[3] = create_test("test_hmap_4", &test_hmap_4); - - run_tests(tests, NUM_TESTS); -} - diff --git a/kernel/tests/test_klibc.h b/kernel/tests/test_klibc.h deleted file mode 100644 index ac6eb649..00000000 --- a/kernel/tests/test_klibc.h +++ /dev/null @@ -1,52 +0,0 @@ -#include "tests.h" -#include "klibc.h" - -#define NUM_TESTS 3 - -int test_os_memcmp_1() { - char buffer1[] = "DWgaOtP12df0"; - char buffer2[] = "DWGAOTP12DF0"; - - int i = os_memcmp(buffer1, buffer2, sizeof(buffer1)); - - if (i > 0) { - return TEST_OK; - } else { - return TEST_FAIL; - } -} - -int test_os_memcmp_2() { - char buffer1[] = "DWgaOtP12df0"; - char buffer2[] = "DWgaOtP12df0"; - - int i = os_memcmp(buffer1, buffer2, sizeof(buffer1)); - - if (i == 0) { - return TEST_OK; - } else { - return TEST_FAIL; - } -} - -int test_os_memcmp_3() { - char buffer1[] = "DWGAOTP12DF0"; - char buffer2[] = "DWgaOtP12df0"; - - int i = os_memcmp(buffer1, buffer2, sizeof(buffer1)); - - if (i < 0) { - return TEST_OK; - } else { - return TEST_FAIL; - } -} - -void run_klibc_tests() { - Test *tests[NUM_TESTS]; - tests[0] = create_test("test_os_memcmp_1", &test_os_memcmp_1); - tests[1] = create_test("test_os_memcmp_2", &test_os_memcmp_2); - tests[2] = create_test("test_os_memcmp_3", &test_os_memcmp_3); - - run_tests(tests, NUM_TESTS); -} diff --git a/kernel/tests/test_mem_alloc.c b/kernel/tests/test_mem_alloc.c deleted file mode 100644 index 62b11ecb..00000000 --- a/kernel/tests/test_mem_alloc.c +++ /dev/null @@ -1,99 +0,0 @@ -#include "tests.h" -#include "tests/test_mem_alloc.h" -#include "klibc.h" -#include "vm.h" - -#define NUM_TESTS 1 - -/* -objects += .o files of testthen make blah blah blah of build targetof upper make file, will make kernel with tests -*/ - -int vm_count_free_frames(); - -//nbits is 0-22 -uint32_t gen_rand(uint64_t *state, int nbits) { - *state = *state * 41 + (*state >> 5); - uint32_t mask = ((1 << nbits) - 1) << 10; - uint32_t v = (*state & mask); - return v >> 10; -} - -//Tests the create function -int test_mem_alloc_1() { - if (kmcheck()) { - ERROR("Inconsistent memory to begin with...\n"); - return TEST_FAIL; - } - - // Allocate some memory - char *p = kmalloc(15); - p = kmalloc(15); - os_strcpy(p, "Hello!"); - - DEBUG("%s\n", p); - - if (kmcheck()) { - ERROR("allocate(15) failed.\n\n"); - return TEST_FAIL; - } - - // Allocate a bunch of blocks of "random" size - uint64_t rng = 1234567891; - - char *pntrs[256]; - uint32_t alloced = 0; - int i; - DEBUG("Starting out w/ %u bytes of heap\n", km_size()); - - for (i = 0; i < 256; i++) { - uint32_t size = gen_rand(&rng, 15); - pntrs[i] = kmalloc(size); - alloced += size; - DEBUG("%u %u %u %u %d\n", i, km_size(), size, alloced, - vm_count_free_frames()); - } - - // Test one of them - pntrs[230][0] = 1; - - if(pntrs[230][0] != 1){ - ERROR("%d != 1\n", pntrs[230][0]); - return TEST_FAIL; - } - - if (kmcheck()) { - ERROR("Memory is inconsistent :-(\n"); - return TEST_FAIL; - } - - // Free all the pntrs - for (i = 0; i < 256; i++) { - if (pntrs[i]) { - kfree(pntrs[i]); - } - } - - kfree(p); - - if (kmcheck()) { - ERROR("Memory is inconsistent :-(\n"); - return TEST_FAIL; - } - - DEBUG("heap_size = %d bytes\n", km_size()); - - return TEST_OK; -} - -//function running tests -void run_mem_alloc_tests() { - Test *tests[NUM_TESTS]; - Test a; // We can't rely on kmalloc for a kmalloc test. - a.test_name = "test_mem_alloc_1"; - a.testptr = &test_mem_alloc_1; - tests[0] = &a; - //tests[0] = create_test("test_mem_alloc_1", &test_mem_alloc_1); - os_printf("asdf\n"); - run_tests(tests, NUM_TESTS); -} diff --git a/kernel/tests/test_priority_queue.c b/kernel/tests/test_priority_queue.c deleted file mode 100644 index 2dad0562..00000000 --- a/kernel/tests/test_priority_queue.c +++ /dev/null @@ -1,309 +0,0 @@ -#include "tests.h" -#include "tests/test_priority_queue.h" -#include "data_structures/priority_queue.h" -#include "klibc.h" - -#define NUM_TESTS 6 -#define DEFAULT_COUNT 10 -#define MIN_PRIORITY 20 -#define MAX_PRIORITY -20 - -#define new(a) ((a*) kmalloc(sizeof(a))) -#define del(a) {if(a) kfree(a); a = 0;} -#define ret(q, e) {prq_free(q); return e;} - -//This is where you define the tests you want to run. They return 1 on success and 0 on failure. - -//Tests the create function -int test_prq_1() { - prq_handle * queue; - queue = prq_create(); - if (!queue) { - ERROR("expected value"); - ret(queue, TEST_FAIL); - } - - ret(queue, TEST_OK); - -} - -//Tests the enqueue and dequeue functions -int test_prq_2() { - - prq_handle * queue; - prq_node * hn; - int i; - - queue = prq_create(); - - // Add reverse - for (i = MIN_PRIORITY; i >= MAX_PRIORITY; i--) { - hn = new(prq_node); - hn->priority = i; - prq_enqueue(queue, hn); - } - - // Add forward - for (i = MAX_PRIORITY; i <= MIN_PRIORITY; i++) { - hn = new(prq_node); - hn->priority = i; - prq_enqueue(queue, hn); - } - - for (i = MAX_PRIORITY; i <= MIN_PRIORITY; i++) { - - hn = prq_dequeue(queue); - int priority_1 = hn->priority; - del(hn); - - hn = prq_dequeue(queue); - int priority_2 = hn->priority; - del(hn); - - if (priority_1 != priority_2) { - ERROR("[%d]: expected [%d]\n", priority_1, priority_2); - ret(queue, TEST_FAIL); - } - if (priority_1 != i) { - ERROR("[%d]: expected [%d]\n", priority_1, i); - ret(queue, TEST_FAIL); - } - if (priority_2 != i) { - ERROR("[%d]: expected [%d]\n", priority_2, i); - ret(queue, TEST_FAIL); - } - } - - ret(queue, TEST_OK); -} - -//Tests the enqueue and dequeue functions -int test_prq_3() { - prq_handle * queue; - prq_node * hn; - int p; - - queue = prq_create(); - - hn = new(prq_node); - hn->priority = 0; - prq_enqueue(queue, hn); - - hn = new(prq_node); - hn->priority = -2; - prq_enqueue(queue, hn); - - hn = new(prq_node); - hn->priority = 1; - prq_enqueue(queue, hn); - - hn = new(prq_node); - hn->priority = -10; - prq_enqueue(queue, hn); - - hn = new(prq_node); - hn->priority = 30; - prq_enqueue(queue, hn); - - hn = prq_dequeue(queue); - p = hn->priority; - del(hn); - - if (p != -10) { - ERROR("[%d]: expected [%d]\n", p, -10); - ret(queue, TEST_FAIL); - } - - hn = prq_dequeue(queue); - p = hn->priority; - del(hn); - - if (p != -2) { - ERROR("[%d]: expected [%d]\n", p, -2); - ret(queue, TEST_FAIL); - } - - hn = new(prq_node); - hn->priority = 2; - prq_enqueue(queue, hn); - - hn = prq_dequeue(queue); - p = hn->priority; - del(hn); - - if (p != 0) { - ERROR("[%d]: expected [%d]\n", p, 0); - ret(queue, TEST_FAIL); - } - - prq_dequeue(queue); - - hn = prq_dequeue(queue); - p = hn->priority; - del(hn); - - if (p != 2) { - ERROR("[%d]: expected [%d]\n", p, 2); - ret(queue, TEST_FAIL); - } - - hn = prq_dequeue(queue); - p = hn->priority; - del(hn); - - if (p != 30) { - ERROR("[%d]: expected [%d]\n", p, 30); - ret(queue, TEST_FAIL); - } - - ret(queue, TEST_OK); - -} - -//testing peek function -int test_prq_4() { - prq_handle * queue; - prq_node * hn; - queue = prq_create(); - - if (prq_peek(queue) && queue->count < 1) { - ERROR("expected [%d]\n", 0); - ret(queue, TEST_FAIL); - } - - hn = new(prq_node); - hn->priority = 0; - prq_enqueue(queue, hn); - - hn = new(prq_node); - hn->priority = 1; - prq_enqueue(queue, hn); - - hn = new(prq_node); - hn->priority = 3; - prq_enqueue(queue, hn); - - hn = prq_dequeue(queue); - del(hn); - - hn = prq_dequeue(queue); - del(hn); - - hn = prq_dequeue(queue); - del(hn); - - if (prq_peek(queue) && queue->count < 1) { - ERROR("expected [%d]\n", 0); - ret(queue, TEST_FAIL); - } - - ret(queue, TEST_OK); - -} - -//testing functionality of prq_create vs prq_fixed_create -int test_prq_5() { - prq_handle * queue1; - prq_node * hn1; - queue1 = prq_create(); - - hn1 = new(prq_node); - hn1->priority = 0; - prq_enqueue(queue1, hn1); - - prq_handle * queue2; - prq_node * hn2; - queue2 = prq_create_fixed(DEFAULT_COUNT); - - hn2 = new(prq_node); - hn2->priority = 0; - prq_enqueue(queue2, hn2); - - if (queue1->heap_size != queue2->heap_size) { - ERROR("expected equal heap_size"); - ret(queue1, TEST_FAIL); - } - - ret(queue1, TEST_OK); -} - -// Test remove function -int test_prq_6() { - prq_handle * queue1; - prq_handle * queue2; - prq_node * hn1; - prq_node * hn2; - prq_node * hn3; - prq_node * hn4; - prq_node * tmp1; - prq_node * tmp2; - - queue1 = prq_create(); - queue2 = prq_create(); - - hn1 = new(prq_node); - hn1->priority = 1; - - hn2 = new(prq_node); - hn2->priority = 2; - - hn3 = new(prq_node); - hn3->priority = 3; - - hn4 = new(prq_node); - hn4->priority = 4; - - prq_enqueue(queue1, hn1); - prq_enqueue(queue1, hn2); - prq_enqueue(queue1, hn3); - prq_enqueue(queue1, hn4); - prq_remove(queue1, hn1); - prq_remove(queue1, hn3); - // Double remove - prq_remove(queue1, hn3); - - prq_enqueue(queue2, hn2); - prq_enqueue(queue2, hn4); - - - if (queue1->count != queue2->count) { - ERROR("expected equal heap_size"); - for(int i = 0; i < queue1->count; ++i) { - prq_node * tmp = prq_dequeue(queue1); - del(tmp); - } - del(queue2); - ret(queue1, TEST_FAIL); - } - - for (int size = 0; size < queue1->count; ++size) { - tmp1 = prq_dequeue(queue1); - tmp2 = prq_dequeue(queue2); - if (tmp1->priority != tmp2->priority) { - del(tmp1); - for(int i = 0; i < queue1->count; ++i) { - prq_node * tmp = prq_dequeue(queue1); - del(tmp); - } - del(queue2); - ret(queue1, TEST_FAIL); - } - del(tmp1); - } - del(queue2); - ret(queue1, TEST_OK); -} - -//function running tests -void run_prq_tests() { - Test *tests[NUM_TESTS]; - tests[0] = create_test("test_prq_1", &test_prq_1); - tests[1] = create_test("test_prq_2", &test_prq_2); - tests[2] = create_test("test_prq_3", &test_prq_3); - tests[3] = create_test("test_prq_4", &test_prq_4); - tests[4] = create_test("test_prq_5", &test_prq_5); - tests[5] = create_test("test_prq_6", &test_prq_6); - - run_tests(tests, NUM_TESTS); -} - diff --git a/kernel/tests/test_vm.c b/kernel/tests/test_vm.c deleted file mode 100644 index 6bec6944..00000000 --- a/kernel/tests/test_vm.c +++ /dev/null @@ -1,160 +0,0 @@ -#include "tests.h" -#include "klibc.h" -#include "memory.h" -#include "vm.h" - -#define NUM_TESTS 1 - -int test_vm_1() { - os_printf("asdf\n"); - - struct vas *vas1 = vm_new_vas(); - LOG("Got new vas at 0x%X\n", vas1); - - // We're part of the kernel, which is already mapped into vas1. - // But our stack isn't, so let's add that mapping. - unsigned int mystack = (unsigned int) &vas1; - mystack &= 0xFFF00000; // Round down to nearest MB - LOG("Stack addr: 0x%X\n", mystack); - LOG("Created page table w/ 0xFFF00000's entry = 0x%X\n", - vas1->l1_pagetable[V_KDSBASE>>20]); - - vm_enable_vas(vas1); - - // Can we still print? - INFO("Hey, I'm printing!\n"); - - // Do we still have the stack? - // FIXME Update constant as necessary -#define STACK_ADDR 0xF020000C - if (((int) vas1) != STACK_ADDR) { - ERROR("Invalid stack"); - return TEST_FAIL; - } - - struct vas *vas2 = (struct vas*) V_L1PTBASE; - INFO("%X (%X)\n", vas2, &vas2); - INFO("%X\n", *((unsigned int* ) vas2)); - INFO("%X\n", vas2->l1_pagetable); - INFO("Entry: %x\n", - vas1->l1_pagetable[(unsigned int ) vas2->l1_pagetable >> 20]); - INFO("%X\n", vas2->l1_pagetable[0]); - INFO("(deref: entry at 0x200000: 0x%X)\n", - vas2->l1_pagetable[0x200000 >> 20]); - - // Test making a thing in this thing - struct vas *vas3 = vm_new_vas(); - vm_enable_vas(vas3); - INFO("%X and %X and %X\n", vas1, vas2, vas3); - - // Test allocating frames... -#define P3_BASE 0x24000000 - int retval = vm_allocate_page(vas3, (void*) P3_BASE, - VM_PERM_PRIVILEGED_RW); - - if (retval) { - ERROR("ERROR: vm_allocate_page returned %x\n", retval); - return TEST_FAIL; - } - - int *p = (int*) 0xFFFFFFF0; - p[0] = 1; - - if (p[0] != 1) { - ERROR("0x%x == 1?\n", p[0]); - return TEST_FAIL; - } - - // Oh man! We should be able to write to there! - p = (int*) P3_BASE; - p[0] = 1; - - LOG("%x %x\n", &p, p); - - if (p[0] != 1) { - ERROR("0x%x == 1?\n", p[0]); - return TEST_FAIL; - } - - // Test shared memory... - LOG("Testing shared memory...\n"); - int *p_3 = (int*) P3_BASE;//0x24000000; - int *p_1 = (int*) 0x31000000; - retval = vm_map_shared_memory(vas1, p_1, vas3, p_3, VM_PERM_PRIVILEGED_RW); - LOG("map_shared_memory returned %d\n", retval); - - p_3[0] = 321; - vm_enable_vas(vas1); - if (p_1[0] != 321) { - ERROR("0x%x == 321?", p_1[0]); - return TEST_FAIL; - } - p_1[1] = 456; - - vm_enable_vas(vas3); - if (p_3[1] != 456) { - ERROR("0x%x == 456?", p_3[1]); - return TEST_FAIL; - } - - // Test allocating many frames... - /*p += BLOCK_SIZE; - while (!vm_allocate_page(vas3, (void*) p, 0)) { - //LOG("Allocated memory...\n"); - p += BLOCK_SIZE; - } - - p -= BLOCK_SIZE; - LOG("Highest frame allocated: 0x%X\n", p); - - while ((unsigned int) p > P3_BASE) { - //LOG("Freed memory...\n"); - vm_free_page(vas3, p); - p -= BLOCK_SIZE; - }*/ - - // Test the data abort... - WARN("You should see a data abort...\n"); - int i = p[-1]; - LOG("%d\n", i); - - // Free the page! - LOG("Freeing page at %X\n", p); - vm_free_page(vas3, p); - - // Clean up & switch back to the kernel's VAS before we return. - vm_enable_vas((struct vas*) KERNEL_VAS); - - return TEST_OK; -} - -void vm_test_early() { - os_printf("Test code for VM (early).\n"); - -#if 0 - // Test 4KB pages - os_printf("0x%X\n", ((unsigned int *)(V_L1PTBASE + PAGE_TABLE_SIZE))[(PMAPBASE+0x100000)>>20]); - os_printf("entry at the address: 0x%X\n", ((unsigned int *)(V_L1PTBASE + PAGE_TABLE_SIZE))[(PMAPBASE+0x100000)>>20]); - unsigned int *p2 = (unsigned int*)(PMAPBASE+0x100000); - os_printf("0x%X\n",p2); - p2[1]++; - p2[1023]++; - os_printf("Should not have seen a page fault, should see one now.\n"); - p2[1024]++; - - // Hey, let's check the access bit now. - p2 = ((unsigned int *)(V_L1PTBASE + PAGE_TABLE_SIZE)); - os_printf("Entry is the address: 0x%X\n", ((unsigned int *)(V_L1PTBASE + PAGE_TABLE_SIZE))[(PMAPBASE+0x100000)>>20]); -#endif - - os_printf("Leaving early test code for VM.\n"); - //while (1); -} - -void run_vm_tests() { - Test *tests[NUM_TESTS]; - tests[0] = create_test("test_vm_1", &test_vm_1); - run_tests(tests, NUM_TESTS); - // Just in case it returned in error... - //vm_enable_vas((struct vas*) KERNEL_VAS); -} diff --git a/kernel/tests/testingsuite_example/.DS_Store b/kernel/tests/testingsuite_example/.DS_Store deleted file mode 100644 index fb0c2723..00000000 Binary files a/kernel/tests/testingsuite_example/.DS_Store and /dev/null differ diff --git a/kernel/tests/testingsuite_example/arrayfill/a.out b/kernel/tests/testingsuite_example/arrayfill/a.out deleted file mode 100755 index 1be2cdbf..00000000 Binary files a/kernel/tests/testingsuite_example/arrayfill/a.out and /dev/null differ diff --git a/kernel/tests/testingsuite_example/arrayfill/arrayfill.c b/kernel/tests/testingsuite_example/arrayfill/arrayfill.c deleted file mode 100644 index b811254b..00000000 --- a/kernel/tests/testingsuite_example/arrayfill/arrayfill.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "arrayfill.h" - -void arrfill(int n) { - int i; - int temp = 1; - for (i = 0; i < n; i++) { - arr[i] = temp; - temp++; - } -} - -int main () { - arrfill(5); - int i; - int size = 5; - for (i = 0; i < size; ++i) { - printf("%d ", arr[i]); - } - printf("\n"); - return 0; -} \ No newline at end of file diff --git a/kernel/tests/testingsuite_example/arrayfill/arrayfill.h b/kernel/tests/testingsuite_example/arrayfill/arrayfill.h deleted file mode 100644 index 9f0833f3..00000000 --- a/kernel/tests/testingsuite_example/arrayfill/arrayfill.h +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#define SIZEARRAY(x) (sizeof(x) / sizeof ((x[0])) - -int arr[100]; - -void arrfill(int); - -void print(); \ No newline at end of file diff --git a/kernel/tests/testingsuite_example/arrayfill/tap.c b/kernel/tests/testingsuite_example/arrayfill/tap.c deleted file mode 100755 index 37f509e8..00000000 --- a/kernel/tests/testingsuite_example/arrayfill/tap.c +++ /dev/null @@ -1,369 +0,0 @@ -/* -libtap - Write tests in C -Copyright 2012 Jake Gelbman -This file is licensed under the GPLv2 or any later version -*/ - -#define _DEFAULT_SOURCE 1 - -#include -#include -#include -#include -#include "tap.h" - -static int expected_tests = NO_PLAN; -static int failed_tests; -static int current_test; -static char *todo_mesg; - -static char * -vstrdupf (const char *fmt, va_list args) { - char *str; - int size; - va_list args2; - va_copy(args2, args); - if (!fmt) - fmt = ""; - size = vsnprintf(NULL, 0, fmt, args2) + 2; - str = malloc(size); - if (!str) { - perror("malloc error"); - exit(1); - } - vsprintf(str, fmt, args); - va_end(args2); - return str; -} - -void -tap_plan (int tests, const char *fmt, ...) { - expected_tests = tests; - if (tests == SKIP_ALL) { - char *why; - va_list args; - va_start(args, fmt); - why = vstrdupf(fmt, args); - va_end(args); - printf("1..0 "); - note("SKIP %s\n", why); - exit(0); - } - if (tests != NO_PLAN) { - printf("1..%d\n", tests); - } -} - -int -vok_at_loc (const char *file, int line, int test, const char *fmt, - va_list args) -{ - char *name = vstrdupf(fmt, args); - if (!test) - printf("not "); - printf("ok %d", ++current_test); - if (*name) - printf(" - %s", name); - if (todo_mesg) { - printf(" # TODO"); - if (*todo_mesg) - printf(" %s", todo_mesg); - } - printf("\n"); - if (!test) { - fprintf(stderr, "# Failed "); - if (todo_mesg) - fprintf(stderr, "(TODO) "); - fprintf(stderr, "test "); - if (*name) - fprintf(stderr, "'%s'\n# ", name); - fprintf(stderr, "at %s line %d.\n", file, line); - if (!todo_mesg) - failed_tests++; - } - free(name); - return test; -} - -int -ok_at_loc (const char *file, int line, int test, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - vok_at_loc(file, line, test, fmt, args); - va_end(args); - return test; -} - -static int -mystrcmp (const char *a, const char *b) { - return a == b ? 0 : !a ? -1 : !b ? 1 : strcmp(a, b); -} - -#define eq(a, b) (!mystrcmp(a, b)) -#define ne(a, b) (mystrcmp(a, b)) - -int -is_at_loc (const char *file, int line, const char *got, const char *expected, - const char *fmt, ...) -{ - int test = eq(got, expected); - va_list args; - va_start(args, fmt); - vok_at_loc(file, line, test, fmt, args); - va_end(args); - if (!test) { - diag(" got: '%s'", got); - diag(" expected: '%s'", expected); - } - return test; -} - -int -isnt_at_loc (const char *file, int line, const char *got, const char *expected, - const char *fmt, ...) -{ - int test = ne(got, expected); - va_list args; - va_start(args, fmt); - vok_at_loc(file, line, test, fmt, args); - va_end(args); - if (!test) { - diag(" got: '%s'", got); - diag(" expected: anything else"); - } - return test; -} - -int -cmp_ok_at_loc (const char *file, int line, int a, const char *op, int b, - const char *fmt, ...) -{ - int test = eq(op, "||") ? a || b - : eq(op, "&&") ? a && b - : eq(op, "|") ? a | b - : eq(op, "^") ? a ^ b - : eq(op, "&") ? a & b - : eq(op, "==") ? a == b - : eq(op, "!=") ? a != b - : eq(op, "<") ? a < b - : eq(op, ">") ? a > b - : eq(op, "<=") ? a <= b - : eq(op, ">=") ? a >= b - : eq(op, "<<") ? a << b - : eq(op, ">>") ? a >> b - : eq(op, "+") ? a + b - : eq(op, "-") ? a - b - : eq(op, "*") ? a * b - : eq(op, "/") ? a / b - : eq(op, "%") ? a % b - : diag("unrecognized operator '%s'", op); - va_list args; - va_start(args, fmt); - vok_at_loc(file, line, test, fmt, args); - va_end(args); - if (!test) { - diag(" %d", a); - diag(" %s", op); - diag(" %d", b); - } - return test; -} - -static int -find_mem_diff (const char *a, const char *b, size_t n, size_t *offset) { - size_t i; - if (a == b) - return 0; - if (!a || !b) - return 2; - for (i = 0; i < n; i++) { - if (a[i] != b[i]) { - *offset = i; - return 1; - } - } - return 0; -} - -int -cmp_mem_at_loc (const char *file, int line, const void *got, - const void *expected, size_t n, const char *fmt, ...) -{ - size_t offset; - int diff = find_mem_diff(got, expected, n, &offset); - va_list args; - va_start(args, fmt); - vok_at_loc(file, line, !diff, fmt, args); - va_end(args); - if (diff == 1) { - diag(" Difference starts at offset %d", offset); - diag(" got: 0x%02x", ((unsigned char *)got)[offset]); - diag(" expected: 0x%02x", ((unsigned char *)expected)[offset]); - } - else if (diff == 2) { - diag(" got: %s", got ? "not NULL" : "NULL"); - diag(" expected: %s", expected ? "not NULL" : "NULL"); - } - return !diff; -} - -static void -vdiag_to_fh (FILE *fh, const char *fmt, va_list args) { - char *mesg, *line; - int i; - if (!fmt) - return; - mesg = vstrdupf(fmt, args); - line = mesg; - for (i = 0; *line; i++) { - char c = mesg[i]; - if (!c || c == '\n') { - mesg[i] = '\0'; - fprintf(fh, "# %s\n", line); - if (!c) - break; - mesg[i] = c; - line = mesg + i + 1; - } - } - free(mesg); - return; -} - -int -diag (const char *fmt, ...) { - va_list args; - va_start(args, fmt); - vdiag_to_fh(stderr, fmt, args); - va_end(args); - return 0; -} - -int -note (const char *fmt, ...) { - va_list args; - va_start(args, fmt); - vdiag_to_fh(stdout, fmt, args); - va_end(args); - return 0; -} - -int -exit_status () { - int retval = 0; - if (expected_tests == NO_PLAN) { - printf("1..%d\n", current_test); - } - else if (current_test != expected_tests) { - diag("Looks like you planned %d test%s but ran %d.", - expected_tests, expected_tests > 1 ? "s" : "", current_test); - retval = 2; - } - if (failed_tests) { - diag("Looks like you failed %d test%s of %d run.", - failed_tests, failed_tests > 1 ? "s" : "", current_test); - retval = 1; - } - return retval; -} - -int -bail_out (int ignore, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - printf("Bail out! "); - vprintf(fmt, args); - printf("\n"); - va_end(args); - exit(255); - return 0; -} - -void -tap_skip (int n, const char *fmt, ...) { - char *why; - va_list args; - va_start(args, fmt); - why = vstrdupf(fmt, args); - va_end(args); - while (n --> 0) { - printf("ok %d ", ++current_test); - note("skip %s\n", why); - } - free(why); -} - -void -tap_todo (int ignore, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - todo_mesg = vstrdupf(fmt, args); - va_end(args); -} - -void -tap_end_todo () { - free(todo_mesg); - todo_mesg = NULL; -} - -#ifndef _WIN32 -#include -#include -#include - -#if defined __APPLE__ || defined BSD -#define MAP_ANONYMOUS MAP_ANON -#endif - -/* Create a shared memory int to keep track of whether a piece of code executed -dies. to be used in the dies_ok and lives_ok macros. */ -int -tap_test_died (int status) { - static int *test_died = NULL; - int prev; - if (!test_died) { - test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANONYMOUS, -1, 0); - *test_died = 0; - } - prev = *test_died; - *test_died = status; - return prev; -} - -int -like_at_loc (int for_match, const char *file, int line, const char *got, - const char *expected, const char *fmt, ...) -{ - int test; - regex_t re; - va_list args; - int err = regcomp(&re, expected, REG_EXTENDED); - if (err) { - char errbuf[256]; - regerror(err, &re, errbuf, sizeof errbuf); - fprintf(stderr, "Unable to compile regex '%s': %s at %s line %d\n", - expected, errbuf, file, line); - exit(255); - } - err = regexec(&re, got, 0, NULL, 0); - regfree(&re); - test = for_match ? !err : err; - va_start(args, fmt); - vok_at_loc(file, line, test, fmt, args); - va_end(args); - if (!test) { - if (for_match) { - diag(" '%s'", got); - diag(" doesn't match: '%s'", expected); - } - else { - diag(" '%s'", got); - diag(" matches: '%s'", expected); - } - } - return test; -} -#endif - diff --git a/kernel/tests/testingsuite_example/arrayfill/tap.h b/kernel/tests/testingsuite_example/arrayfill/tap.h deleted file mode 100755 index 302e6d85..00000000 --- a/kernel/tests/testingsuite_example/arrayfill/tap.h +++ /dev/null @@ -1,117 +0,0 @@ -/* -libtap - Write tests in C -Copyright 2012 Jake Gelbman -This file is licensed under the GPLv2 or any later version -*/ - -#ifndef __TAP_H__ -#define __TAP_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef va_copy -#ifdef __va_copy -#define va_copy __va_copy -#else -#define va_copy(d, s) ((d) = (s)) -#endif -#endif - -#include -#include -#include - -int vok_at_loc (const char *file, int line, int test, const char *fmt, - va_list args); -int ok_at_loc (const char *file, int line, int test, const char *fmt, - ...); -int is_at_loc (const char *file, int line, const char *got, - const char *expected, const char *fmt, ...); -int isnt_at_loc (const char *file, int line, const char *got, - const char *expected, const char *fmt, ...); -int cmp_ok_at_loc (const char *file, int line, int a, const char *op, - int b, const char *fmt, ...); -int cmp_mem_at_loc (const char *file, int line, const void *got, - const void *expected, size_t n, const char *fmt, ...); -int bail_out (int ignore, const char *fmt, ...); -void tap_plan (int tests, const char *fmt, ...); -int diag (const char *fmt, ...); -int note (const char *fmt, ...); -int exit_status (void); -void tap_skip (int n, const char *fmt, ...); -void tap_todo (int ignore, const char *fmt, ...); -void tap_end_todo (void); - -#define NO_PLAN -1 -#define SKIP_ALL -2 -#define ok(...) ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) -#define is(...) is_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) -#define isnt(...) isnt_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) -#define cmp_ok(...) cmp_ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL) -#define cmp_mem(...) cmp_mem_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL); -#define plan(...) tap_plan(__VA_ARGS__, NULL) -#define done_testing() return exit_status() -#define BAIL_OUT(...) bail_out(0, "" __VA_ARGS__, NULL) -#define pass(...) ok(1, "" __VA_ARGS__) -#define fail(...) ok(0, "" __VA_ARGS__) - -#define skip(test, ...) do {if (test) {tap_skip(__VA_ARGS__, NULL); break;} -#define end_skip } while (0) - -#define todo(...) tap_todo(0, "" __VA_ARGS__, NULL) -#define end_todo tap_end_todo() - -#define dies_ok(...) dies_ok_common(1, __VA_ARGS__) -#define lives_ok(...) dies_ok_common(0, __VA_ARGS__) - -#ifdef _WIN32 -#define like(...) tap_skip(1, "like is not implemented on Windows") -#define unlike tap_skip(1, "unlike is not implemented on Windows") -#define dies_ok_common(...) \ - tap_skip(1, "Death detection is not supported on Windows") -#else -#define like(...) like_at_loc(1, __FILE__, __LINE__, __VA_ARGS__, NULL) -#define unlike(...) like_at_loc(0, __FILE__, __LINE__, __VA_ARGS__, NULL) -int like_at_loc (int for_match, const char *file, int line, - const char *got, const char *expected, - const char *fmt, ...); -#include -#include -#include -int tap_test_died (int status); -#define dies_ok_common(for_death, code, ...) \ - do { \ - int cpid; \ - int it_died; \ - tap_test_died(1); \ - cpid = fork(); \ - switch (cpid) { \ - case -1: \ - perror("fork error"); \ - exit(1); \ - case 0: \ - close(1); \ - close(2); \ - code \ - tap_test_died(0); \ - exit(0); \ - } \ - if (waitpid(cpid, NULL, 0) < 0) { \ - perror("waitpid error"); \ - exit(1); \ - } \ - it_died = tap_test_died(0); \ - if (!it_died) \ - {code} \ - ok(for_death ? it_died : !it_died, "" __VA_ARGS__); \ - } while (0) -#endif - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/kernel/tests/testingsuite_example/arrayfill/testarrayfill.c b/kernel/tests/testingsuite_example/arrayfill/testarrayfill.c deleted file mode 100644 index 1426bf18..00000000 --- a/kernel/tests/testingsuite_example/arrayfill/testarrayfill.c +++ /dev/null @@ -1,28 +0,0 @@ -// #include -// #include "arrayfill.h" - -// int first_element() { -// if (arr[0] == 1) { -// return 1; -// } -// else { -// return 0; -// } -// } - -// int main() { -// plan(1); -// ok(first_element(), "checks the first element"); -// done_testing(); -// } - -#include "tap.h" -int main() { - plan(1); - ok(3 == 3); - done_testing(); -} - - - - diff --git a/kernel/threads/kthreads.c b/kernel/threads/kthreads.c deleted file mode 100644 index 420148b8..00000000 --- a/kernel/threads/kthreads.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * kthreads.c - * - * Created on: Apr 23, 2015 - * Author: mwkurian - */ - -#include "kthread.h" -#include - -kthread_handle* kthread_create(kthread_callback_handler cb_handler) -{ - kthread_handle * kthread = kmalloc(sizeof(kthread_handle)); - kthread->cb_handler = cb_handler; - return kthread; -} - -uint32_t kthread_start(kthread_handle * kthread) -{ - sched_task * task = sched_create_task(kthread); - sched_add_task(task); -} - diff --git a/kernel/uboot-commands.ubt b/kernel/uboot-commands.ubt deleted file mode 100644 index c6945626..00000000 --- a/kernel/uboot-commands.ubt +++ /dev/null @@ -1,2 +0,0 @@ -setenv bootargs root=/dev/ram mem=128M -load /hello -bootm 0x210000 diff --git a/kernel/vm/fastlz/6pack.c b/kernel/vm/fastlz/6pack.c deleted file mode 100644 index 89a1128d..00000000 --- a/kernel/vm/fastlz/6pack.c +++ /dev/null @@ -1,636 +0,0 @@ -/* - 6PACK - file compressor using FastLZ (lightning-fast compression library) - - Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#define SIXPACK_VERSION_MAJOR 0 -#define SIXPACK_VERSION_MINOR 1 -#define SIXPACK_VERSION_REVISION 0 -#define SIXPACK_VERSION_STRING "snapshot 20070615" - -#include "fastlz.h" - -#undef PATH_SEPARATOR - -#if defined(MSDOS) || defined(__MSDOS__) || defined(MSDOS) -#define PATH_SEPARATOR '\\' -#endif - -#if defined(WIN32) || defined(__NT__) || defined(_WIN32) || defined(__WIN32__) -#define PATH_SEPARATOR '\\' -#if defined(__BORLANDC__) || defined(_MSC_VER) -#define inline __inline -#endif -#endif - -#ifndef PATH_SEPARATOR -#define PATH_SEPARATOR '/' -#endif - -#undef SIXPACK_BENCHMARK_WIN32 -#if defined(WIN32) || defined(__NT__) || defined(_WIN32) || defined(__WIN32__) -#if defined(_MSC_VER) || defined(__GNUC__) -#define SIXPACK_BENCHMARK_WIN32 -#include -#endif -#endif - -/* magic identifier for 6pack file */ -static unsigned char sixpack_magic[8] = {137, '6', 'P', 'K', 13, 10, 26, 10}; - -#define BLOCK_SIZE (2*64*1024) - -/* prototypes */ -static inline unsigned long update_adler32(unsigned long checksum, const void *buf, int len); -void usage(void); -int detect_magic(FILE *f); -void write_magic(FILE *f); -void write_chunk_header(FILE* f, int id, int options, unsigned long size, -unsigned long checksum, unsigned long extra); -unsigned long block_compress(const unsigned char* input, unsigned long length, unsigned char* output); -int pack_file_compressed(const char* input_file, int method, int level, FILE* f); -int pack_file(int compress_level, const char* input_file, const char* output_file); - -/* for Adler-32 checksum algorithm, see RFC 1950 Section 8.2 */ -#define ADLER32_BASE 65521 -static inline unsigned long update_adler32(unsigned long checksum, const void *buf, int len) -{ - const unsigned char* ptr = (const unsigned char*)buf; - unsigned long s1 = checksum & 0xffff; - unsigned long s2 = (checksum >> 16) & 0xffff; - - while(len>0) - { - unsigned k = len < 5552 ? len : 5552; - len -= k; - - while(k >= 8) - { - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - k -= 8; - } - - while(k-- > 0) - { - s1 += *ptr++; s2 += s1; - } - s1 = s1 % ADLER32_BASE; - s2 = s2 % ADLER32_BASE; - } - return (s2 << 16) + s1; -} - -void usage(void) -{ - printf("6pack: high-speed file compression tool\n"); - printf("Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)\n"); - printf("\n"); - printf("Usage: 6pack [options] input-file output-file\n"); - printf("\n"); - printf("Options:\n"); - printf(" -1 compress faster\n"); - printf(" -2 compress better\n"); - printf(" -v show program version\n"); -#ifdef SIXPACK_BENCHMARK_WIN32 - printf(" -mem check in-memory compression speed\n"); -#endif - printf("\n"); -} - -/* return non-zero if magic sequence is detected */ -/* warning: reset the read pointer to the beginning of the file */ -int detect_magic(FILE *f) -{ - unsigned char buffer[8]; - size_t bytes_read; - int c; - - fseek(f, SEEK_SET, 0); - bytes_read = fread(buffer, 1, 8, f); - fseek(f, SEEK_SET, 0); - if(bytes_read < 8) - return 0; - - for(c = 0; c < 8; c++) - if(buffer[c] != sixpack_magic[c]) - return 0; - - return -1; -} - -void write_magic(FILE *f) -{ - fwrite(sixpack_magic, 8, 1, f); -} - -void write_chunk_header(FILE* f, int id, int options, unsigned long size, - unsigned long checksum, unsigned long extra) -{ - unsigned char buffer[16]; - - buffer[0] = id & 255; - buffer[1] = id >> 8; - buffer[2] = options & 255; - buffer[3] = options >> 8; - buffer[4] = size & 255; - buffer[5] = (size >> 8) & 255; - buffer[6] = (size >> 16) & 255; - buffer[7] = (size >> 24) & 255; - buffer[8] = checksum & 255; - buffer[9] = (checksum >> 8) & 255; - buffer[10] = (checksum >> 16) & 255; - buffer[11] = (checksum >> 24) & 255; - buffer[12] = extra & 255; - buffer[13] = (extra >> 8) & 255; - buffer[14] = (extra >> 16) & 255; - buffer[15] = (extra >> 24) & 255; - - fwrite(buffer, 16, 1, f); -} - -int pack_file_compressed(const char* input_file, int method, int level, FILE* f) -{ - FILE* in; - unsigned long fsize; - unsigned long checksum; - const char* shown_name; - unsigned char buffer[BLOCK_SIZE]; - unsigned char result[BLOCK_SIZE*2]; /* FIXME twice is too large */ - unsigned char progress[20]; - int c; - unsigned long percent; - unsigned long total_read; - unsigned long total_compressed; - int chunk_size; - - /* sanity check */ - in = fopen(input_file, "rb"); - if(!in) - { - printf("Error: could not open %s\n", input_file); - return -1; - } - - /* find size of the file */ - fseek(in, 0, SEEK_END); - fsize = ftell(in); - fseek(in, 0, SEEK_SET); - - /* already a 6pack archive? */ - if(detect_magic(in)) - { - printf("Error: file %s is already a 6pack archive!\n", input_file); - fclose(in); - return -1; - } - - /* truncate directory prefix, e.g. "foo/bar/FILE.txt" becomes "FILE.txt" */ - shown_name = input_file + strlen(input_file) - 1; - while(shown_name > input_file) - if(*(shown_name-1) == PATH_SEPARATOR) - break; - else - shown_name--; - - /* chunk for File Entry */ - buffer[0] = fsize & 255; - buffer[1] = (fsize >> 8) & 255; - buffer[2] = (fsize >> 16) & 255; - buffer[3] = (fsize >> 24) & 255; -#if 0 - buffer[4] = (fsize >> 32) & 255; - buffer[5] = (fsize >> 40) & 255; - buffer[6] = (fsize >> 48) & 255; - buffer[7] = (fsize >> 56) & 255; -#else - /* because fsize is only 32-bit */ - buffer[4] = 0; - buffer[5] = 0; - buffer[6] = 0; - buffer[7] = 0; -#endif - buffer[8] = (strlen(shown_name)+1) & 255; - buffer[9] = (strlen(shown_name)+1) >> 8; - checksum = 1L; - checksum = update_adler32(checksum, buffer, 10); - checksum = update_adler32(checksum, shown_name, strlen(shown_name)+1); - write_chunk_header(f, 1, 0, 10+strlen(shown_name)+1, checksum, 0); - fwrite(buffer, 10, 1, f); - fwrite(shown_name, strlen(shown_name)+1, 1, f); - total_compressed = 16 + 10 + strlen(shown_name)+1; - - /* for progress status */ - memset(progress, ' ', 20); - if(strlen(shown_name) < 16) - for(c = 0; c < (int)strlen(shown_name); c++) - progress[c] = shown_name[c]; - else - { - for(c = 0; c < 13; c++) - progress[c] = shown_name[c]; - progress[13] = '.'; - progress[14] = '.'; - progress[15] = ' '; - } - progress[16] = '['; - progress[17] = 0; - printf("%s", progress); - for(c = 0; c < 50; c++) - printf("."); - printf("]\r"); - printf("%s", progress); - - /* read file and place in archive */ - total_read = 0; - percent = 0; - for(;;) - { - int compress_method = method; - int last_percent = (int)percent; - size_t bytes_read = fread(buffer, 1, BLOCK_SIZE, in); - if(bytes_read == 0) - break; - total_read += bytes_read; - - /* for progress */ - if(fsize < (1<<24)) - percent = total_read * 100 / fsize; - else - percent = total_read/256 * 100 / (fsize >>8); - percent >>= 1; - while(last_percent < (int)percent) - { - printf("#"); - last_percent++; - } - - /* too small, don't bother to compress */ - if(bytes_read < 32) - compress_method = 0; - - /* write to output */ - switch(compress_method) - { - /* FastLZ */ - case 1: - chunk_size = fastlz_compress_level(level, buffer, bytes_read, result); - checksum = update_adler32(1L, result, chunk_size); - write_chunk_header(f, 17, 1, chunk_size, checksum, bytes_read); - fwrite(result, 1, chunk_size, f); - total_compressed += 16; - total_compressed += chunk_size; - break; - - /* uncompressed, also fallback method */ - case 0: - default: - checksum = 1L; - checksum = update_adler32(checksum, buffer, bytes_read); - write_chunk_header(f, 17, 0, bytes_read, checksum, bytes_read); - fwrite(buffer, 1, bytes_read, f); - total_compressed += 16; - total_compressed += bytes_read; - break; - } - } - - fclose(in); - if(total_read != fsize) - { - printf("\n"); - printf("Error: reading %s failed!\n", input_file); - return -1; - } - else - { - printf("] "); - if(total_compressed < fsize) - { - if(fsize < (1<<20)) - percent = total_compressed * 1000 / fsize; - else - percent = total_compressed/256 * 1000 / (fsize >>8); - percent = 1000 - percent; - printf("%2d.%d%% saved", (int)percent/10, (int)percent%10); - } - printf("\n"); - } - - return 0; -} - -int pack_file(int compress_level, const char* input_file, const char* output_file) -{ - FILE* f; - int result; - - f = fopen(output_file, "rb"); - if(f) - { - fclose(f); - printf("Error: file %s already exists. Aborted.\n\n", output_file); - return -1; - } - - f = fopen(output_file, "wb"); - if(!f) - { - printf("Error: could not create %s. Aborted.\n\n", output_file); - return -1; - } - - write_magic(f); - - result = pack_file_compressed(input_file, 1, compress_level, f); - fclose(f); - - return result; -} - -#ifdef SIXPACK_BENCHMARK_WIN32 -int benchmark_speed(int compress_level, const char* input_file); - -int benchmark_speed(int compress_level, const char* input_file) -{ - FILE* in; - unsigned long fsize; - unsigned long maxout; - const char* shown_name; - unsigned char* buffer; - unsigned char* result; - size_t bytes_read; - - /* sanity check */ - in = fopen(input_file, "rb"); - if(!in) - { - printf("Error: could not open %s\n", input_file); - return -1; - } - - /* find size of the file */ - fseek(in, 0, SEEK_END); - fsize = ftell(in); - fseek(in, 0, SEEK_SET); - - /* already a 6pack archive? */ - if(detect_magic(in)) - { - printf("Error: no benchmark for 6pack archive!\n"); - fclose(in); - return -1; - } - - /* truncate directory prefix, e.g. "foo/bar/FILE.txt" becomes "FILE.txt" */ - shown_name = input_file + strlen(input_file) - 1; - while(shown_name > input_file) - if(*(shown_name-1) == PATH_SEPARATOR) - break; - else - shown_name--; - - maxout = 1.05 * fsize; - maxout = (maxout < 66) ? 66 : maxout; - buffer = (unsigned char*)malloc(fsize); - result = (unsigned char*)malloc(maxout); - if(!buffer || !result) - { - printf("Error: not enough memory!\n"); - free(buffer); - free(result); - fclose(in); - return -1; - } - - printf("Reading source file....\n"); - bytes_read = fread(buffer, 1, fsize, in); - if(bytes_read != fsize) - { - printf("Error reading file %s!\n", shown_name); - printf("Read %d bytes, expecting %d bytes\n", bytes_read, fsize); - free(buffer); - free(result); - fclose(in); - return -1; - } - -/* shamelessly copied from QuickLZ 1.20 test program */ - { - unsigned int j, y; - size_t i, u = 0; - double mbs, fastest; - unsigned long compressed_size; - - printf("Setting HIGH_PRIORITY_CLASS...\n"); - SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); - - printf("Benchmarking FastLZ Level %d, please wait...\n", compress_level); - - i = bytes_read; - fastest = 0.0; - for (j = 0; j < 3; j++) - { - y = 0; - mbs = GetTickCount(); - while(GetTickCount() == mbs); - mbs = GetTickCount(); - while(GetTickCount() - mbs < 3000) /* 1% accuracy with 18.2 timer */ - { - u = fastlz_compress_level(compress_level, buffer, bytes_read, result); - y++; - } - - mbs = ((double)i*(double)y)/((double)(GetTickCount() - mbs)/1000.)/1000000.; - /*printf(" %.1f Mbyte/s ", mbs);*/ - if (fastest < mbs) - fastest = mbs; - } - - printf("\nCompressed %d bytes into %d bytes (%.1f%%) at %.1f Mbyte/s.\n", (unsigned int)i, (unsigned int)u, (double)u/(double)i*100., fastest); - -#if 1 - fastest = 0.0; - compressed_size = u; - for (j = 0; j < 3; j++) - { - y = 0; - mbs = GetTickCount(); - while(GetTickCount() == mbs); - mbs = GetTickCount(); - while(GetTickCount() - mbs < 3000) /* 1% accuracy with 18.2 timer */ - { - u = fastlz_decompress(result, compressed_size, buffer, bytes_read); - y++; - } - - mbs = ((double)i*(double)y)/((double)(GetTickCount() - mbs)/1000.)/1000000.; - /*printf(" %.1f Mbyte/s ", mbs);*/ - if (fastest < mbs) - fastest = mbs; - } - - printf("\nDecompressed at %.1f Mbyte/s.\n\n(1 MB = 1000000 byte)\n", fastest); -#endif - } - - fclose(in); - return 0; -} -#endif /* SIXPACK_BENCHMARK_WIN32 */ - - -int main(int argc, char** argv) -{ - int i; - int compress_level; - int benchmark; - char* input_file; - char* output_file; - - /* show help with no argument at all*/ - if(argc == 1) - { - usage(); - return 0; - } - - /* default compression level, not the fastest */ - compress_level = 2; - - /* do benchmark only when explicitly specified */ - benchmark = 0; - - /* no file is specified */ - input_file = 0; - output_file = 0; - - for(i = 1; i <= argc; i++) - { - char* argument = argv[i]; - - if(!argument) - continue; - - /* display help on usage */ - if(!strcmp(argument, "-h") || !strcmp(argument, "--help")) - { - usage(); - return 0; - } - - /* check for version information */ - if(!strcmp(argument, "-v") || !strcmp(argument, "--version")) - { - printf("6pack: high-speed file compression tool\n"); - printf("Version %s (using FastLZ %s)\n", - SIXPACK_VERSION_STRING, FASTLZ_VERSION_STRING); - printf("Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)\n"); - printf("\n"); - return 0; - } - - /* test compression speed? */ - if(!strcmp(argument, "-mem")) - { - benchmark = 1; - continue; - } - - /* compression level */ - if(!strcmp(argument, "-1") || !strcmp(argument, "--fastest")) - { - compress_level = 1; - continue; - } - if(!strcmp(argument, "-2")) - { - compress_level = 2; - continue; - } - - /* unknown option */ - if(argument[0] == '-') - { - printf("Error: unknown option %s\n\n", argument); - printf("To get help on usage:\n"); - printf(" 6pack --help\n\n"); - return -1; - } - - /* first specified file is input */ - if(!input_file) - { - input_file = argument; - continue; - } - - /* next specified file is output */ - if(!output_file) - { - output_file = argument; - continue; - } - - /* files are already specified */ - printf("Error: unknown option %s\n\n", argument); - printf("To get help on usage:\n"); - printf(" 6pack --help\n\n"); - return -1; - } - - if(!input_file) - { - printf("Error: input file is not specified.\n\n"); - printf("To get help on usage:\n"); - printf(" 6pack --help\n\n"); - return -1; - } - - if(!output_file && !benchmark) - { - printf("Error: output file is not specified.\n\n"); - printf("To get help on usage:\n"); - printf(" 6pack --help\n\n"); - return -1; - } - -#ifdef SIXPACK_BENCHMARK_WIN32 - if(benchmark) - return benchmark_speed(compress_level, input_file); - else -#endif - return pack_file(compress_level, input_file, output_file); - - /* unreachable */ - return 0; -} diff --git a/kernel/vm/fastlz/6unpack.c b/kernel/vm/fastlz/6unpack.c deleted file mode 100644 index b0215f9f..00000000 --- a/kernel/vm/fastlz/6unpack.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - 6PACK - file compressor using FastLZ (lightning-fast compression library) - - Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include -#include -#include - -#define SIXPACK_VERSION_MAJOR 0 -#define SIXPACK_VERSION_MINOR 1 -#define SIXPACK_VERSION_REVISION 0 -#define SIXPACK_VERSION_STRING "0.1.0" - -#include "fastlz.h" - -#if defined(WIN32) || defined(__NT__) || defined(_WIN32) || defined(__WIN32__) -#if defined(__BORLANDC__) || defined(_MSC_VER) -#define inline __inline -#endif -#endif - -/* magic identifier for 6pack file */ -static unsigned char sixpack_magic[8] = {137, '6', 'P', 'K', 13, 10, 26, 10}; - -#define BLOCK_SIZE 65536 - -/* prototypes */ -static inline unsigned long update_adler32(unsigned long checksum, const void *buf, int len); -void usage(void); -int detect_magic(FILE *f); -static inline unsigned long readU16(const unsigned char* ptr); -static inline unsigned long readU32(const unsigned char* ptr); -void read_chunk_header(FILE* f, int* id, int* options, unsigned long* size, -unsigned long* checksum, unsigned long* extra); -int unpack_file(const char* archive_file); - -/* for Adler-32 checksum algorithm, see RFC 1950 Section 8.2 */ -#define ADLER32_BASE 65521 -static inline unsigned long update_adler32(unsigned long checksum, const void *buf, int len) -{ - const unsigned char* ptr = (const unsigned char*)buf; - unsigned long s1 = checksum & 0xffff; - unsigned long s2 = (checksum >> 16) & 0xffff; - - while(len>0) - { - unsigned k = len < 5552 ? len : 5552; - len -= k; - - while(k >= 8) - { - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - s1 += *ptr++; s2 += s1; - k -= 8; - } - - while(k-- > 0) - { - s1 += *ptr++; s2 += s1; - } - s1 = s1 % ADLER32_BASE; - s2 = s2 % ADLER32_BASE; - } - return (s2 << 16) + s1; -} - -void usage(void) -{ - printf("6unpack: uncompress 6pack archive\n"); - printf("Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)\n"); - printf("\n"); - printf("Usage: 6unpack archive-file\n"); - printf("\n"); -} - -/* return non-zero if magic sequence is detected */ -/* warning: reset the read pointer to the beginning of the file */ -int detect_magic(FILE *f) -{ - unsigned char buffer[8]; - size_t bytes_read; - int c; - - fseek(f, SEEK_SET, 0); - bytes_read = fread(buffer, 1, 8, f); - fseek(f, SEEK_SET, 0); - if(bytes_read < 8) - return 0; - - for(c = 0; c < 8; c++) - if(buffer[c] != sixpack_magic[c]) - return 0; - - return -1; -} - -static inline unsigned long readU16( const unsigned char* ptr ) -{ - return ptr[0]+(ptr[1]<<8); -} - -static inline unsigned long readU32( const unsigned char* ptr ) -{ - return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24); -} - -void read_chunk_header(FILE* f, int* id, int* options, unsigned long* size, -unsigned long* checksum, unsigned long* extra) -{ - unsigned char buffer[16]; - fread(buffer, 1, 16, f); - - *id = readU16(buffer) & 0xffff; - *options = readU16(buffer+2) & 0xffff; - *size = readU32(buffer+4) & 0xffffffff; - *checksum = readU32(buffer+8) & 0xffffffff; - *extra = readU32(buffer+12) & 0xffffffff; -} - -int unpack_file(const char* input_file) -{ - FILE* in; - unsigned long fsize; - int c; - unsigned long percent; - unsigned char progress[20]; - int chunk_id; - int chunk_options; - unsigned long chunk_size; - unsigned long chunk_checksum; - unsigned long chunk_extra; - unsigned char buffer[BLOCK_SIZE]; - unsigned long checksum; - - unsigned long decompressed_size; - unsigned long total_extracted; - int name_length; - char* output_file; - FILE* f; - - unsigned char* compressed_buffer; - unsigned char* decompressed_buffer; - unsigned long compressed_bufsize; - unsigned long decompressed_bufsize; - - /* sanity check */ - in = fopen(input_file, "rb"); - if(!in) - { - printf("Error: could not open %s\n", input_file); - return -1; - } - - /* find size of the file */ - fseek(in, 0, SEEK_END); - fsize = ftell(in); - fseek(in, 0, SEEK_SET); - - /* not a 6pack archive? */ - if(!detect_magic(in)) - { - fclose(in); - printf("Error: file %s is not a 6pack archive!\n", input_file); - return -1; - } - - printf("Archive: %s", input_file); - - /* position of first chunk */ - fseek(in, 8, SEEK_SET); - - /* initialize */ - output_file = 0; - f = 0; - total_extracted = 0; - decompressed_size = 0; - percent = 0; - compressed_buffer = 0; - decompressed_buffer = 0; - compressed_bufsize = 0; - decompressed_bufsize = 0; - - /* main loop */ - for(;;) - { - /* end of file? */ - size_t pos = ftell(in); - if(pos >= fsize) - break; - - read_chunk_header(in, &chunk_id, &chunk_options, - &chunk_size, &chunk_checksum, &chunk_extra); - - if((chunk_id == 1) && (chunk_size > 10) && (chunk_size < BLOCK_SIZE)) - { - /* close current file, if any */ - printf("\n"); - free(output_file); - output_file = 0; - if(f) - fclose(f); - - /* file entry */ - fread(buffer, 1, chunk_size, in); - checksum = update_adler32(1L, buffer, chunk_size); - if(checksum != chunk_checksum) - { - free(output_file); - output_file = 0; - fclose(in); - printf("\nError: checksum mismatch!\n"); - printf("Got %08lX Expecting %08lX\n", checksum, chunk_checksum); - return -1; - } - - decompressed_size = readU32(buffer); - total_extracted = 0; - percent = 0; - - /* get file to extract */ - name_length = (int)readU16(buffer+8); - if(name_length > (int)chunk_size - 10) - name_length = chunk_size - 10; - output_file = (char*)malloc(name_length+1); - memset(output_file, 0, name_length+1); - for(c = 0; c < name_length; c++) - output_file[c] = buffer[10+c]; - - /* check if already exists */ - f = fopen(output_file, "rb"); - if(f) - { - fclose(f); - printf("File %s already exists. Skipped.\n", output_file); - free(output_file); - output_file = 0; - f = 0; - } - else - { - /* create the file */ - f = fopen(output_file, "wb"); - if(!f) - { - printf("Can't create file %s. Skipped.\n", output_file); - free(output_file); - output_file = 0; - f = 0; - } - else - { - /* for progress status */ - printf("\n"); - memset(progress, ' ', 20); - if(strlen(output_file) < 16) - for(c = 0; c < (int)strlen(output_file); c++) - progress[c] = output_file[c]; - else - { - for(c = 0; c < 13; c++) - progress[c] = output_file[c]; - progress[13] = '.'; - progress[14] = '.'; - progress[15] = ' '; - } - progress[16] = '['; - progress[17] = 0; - printf("%s", progress); - for(c = 0; c < 50; c++) - printf("."); - printf("]\r"); - printf("%s", progress); - } - } - } - - if((chunk_id == 17) && f && output_file && decompressed_size) - { - unsigned long remaining; - - /* uncompressed */ - switch(chunk_options) - { - /* stored, simply copy to output */ - case 0: - /* read one block at at time, write and update checksum */ - total_extracted += chunk_size; - remaining = chunk_size; - checksum = 1L; - for(;;) - { - unsigned long r = (BLOCK_SIZE < remaining) ? BLOCK_SIZE: remaining; - size_t bytes_read = fread(buffer, 1, r, in); - if(bytes_read == 0) - break; - fwrite(buffer, 1, bytes_read, f); - checksum = update_adler32(checksum, buffer, bytes_read); - remaining -= bytes_read; - } - - /* verify everything is written correctly */ - if(checksum != chunk_checksum) - { - fclose(f); - f = 0; - free(output_file); - output_file = 0; - printf("\nError: checksum mismatch. Aborted.\n"); - printf("Got %08lX Expecting %08lX\n", checksum, chunk_checksum); - } - break; - - /* compressed using FastLZ */ - case 1: - /* enlarge input buffer if necessary */ - if(chunk_size > compressed_bufsize) - { - compressed_bufsize = chunk_size; - free(compressed_buffer); - compressed_buffer = (unsigned char*)malloc(compressed_bufsize); - } - - /* enlarge output buffer if necessary */ - if(chunk_extra > decompressed_bufsize) - { - decompressed_bufsize = chunk_extra; - free(decompressed_buffer); - decompressed_buffer = (unsigned char*)malloc(decompressed_bufsize); - } - - /* read and check checksum */ - fread(compressed_buffer, 1, chunk_size, in); - checksum = update_adler32(1L, compressed_buffer, chunk_size); - total_extracted += chunk_extra; - - /* verify that the chunk data is correct */ - if(checksum != chunk_checksum) - { - fclose(f); - f = 0; - free(output_file); - output_file = 0; - printf("\nError: checksum mismatch. Skipped.\n"); - printf("Got %08lX Expecting %08lX\n", checksum, chunk_checksum); - } - else - { - /* decompress and verify */ - remaining = fastlz_decompress(compressed_buffer, chunk_size, decompressed_buffer, chunk_extra); - if(remaining != chunk_extra) - { - fclose(f); - f = 0; - free(output_file); - output_file = 0; - printf("\nError: decompression failed. Skipped.\n"); - } - else - fwrite(decompressed_buffer, 1, chunk_extra, f); - } - break; - - default: - printf("\nError: unknown compression method (%d)\n", chunk_options); - fclose(f); - f = 0; - free(output_file); - output_file = 0; - break; - } - - /* for progress, if everything is fine */ - if(f) - { - int last_percent = (int)percent; - if(decompressed_size < (1<<24)) - percent = total_extracted * 100 / decompressed_size; - else - percent = total_extracted / 256 * 100 / (decompressed_size >>8); - percent >>= 1; - while(last_percent < (int)percent) - { - printf("#"); - last_percent++; - } - } - } - - /* position of next chunk */ - fseek(in, pos + 16 + chunk_size, SEEK_SET); - } - printf("\n\n"); - - /* free allocated stuff */ - free(compressed_buffer); - free(decompressed_buffer); - free(output_file); - - /* close working files */ - if(f) - fclose(f); - fclose(in); - - /* so far so good */ - return 0; -} - -int main(int argc, char** argv) -{ - int i; - const char* archive_file; - - /* show help with no argument at all*/ - if(argc == 1) - { - usage(); - return 0; - } - - /* check for help on usage */ - for(i = 1; i <= argc; i++) - if(argv[i]) - if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) - { - usage(); - return 0; - } - - /* check for version information */ - for(i = 1; i <= argc; i++) - if(argv[i]) - if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) - { - printf("6unpack: high-speed file compression tool\n"); - printf("Version %s (using FastLZ %s)\n", - SIXPACK_VERSION_STRING, FASTLZ_VERSION_STRING); - printf("Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)\n"); - printf("\n"); - return 0; - } - - /* needs at least two arguments */ - if(argc <= 1) - { - usage(); - return 0; - } - - archive_file = argv[1]; - - return unpack_file(archive_file); -} diff --git a/kernel/vm/fastlz/README.TXT b/kernel/vm/fastlz/README.TXT deleted file mode 100644 index 581e9e8a..00000000 --- a/kernel/vm/fastlz/README.TXT +++ /dev/null @@ -1,75 +0,0 @@ -FastLZ - lightning-fast lossless compression library - -Author: Ariya Hidayat -Official website: http://www.fastlz.org - -FastLZ is distributed using the MIT license, see file LICENSE -for details. - -FastLZ consists of two files: fastlz.h and fastlz.c. Just add these -files to your project in order to use FastLZ. For information on -compression and decompression routines, see fastlz.h. - -A simple file compressor called 6pack is included as an example -on how to use FastLZ. The corresponding decompressor is 6unpack. - -To compile using GCC: - - gcc -o 6pack 6pack.c fastlz.c - gcc -o 6unpack 6unpack.c fastlz.c - -To compile using MinGW: - - mingw32-gcc -o 6pack 6pack.c fastlz.c - mingw32-gcc -o 6unpack 6unpack.c fastlz.c - -To compile using Microsoft Visual C++: - - cl 6pack.c fastlz.c - cl 6unpack.c fastlz.c - -To compile using Borland C++: - - bcc32 6pack.c fastlz.c - bcc32 6unpack.c fastlz.c - -To compile using OpenWatcom C/C++: - - cl386 6pack.c fastlz.c - cl386 6unpack.c fastlz.c - -To compile using Intel C++ compiler for Windows: - - icl 6pack.c fastlz.c - icl 6unpack.c fastlz.c - -To compile using Intel C++ compiler for Linux: - - icc -o 6pack 6pack.c fastlz.c - icc -o 6unpack 6unpack.c fastlz.c - -To compile 6pack using LCC-Win32: - - lc 6pack.c fastlz.c - lc 6unpack.c fastlz.c - -To compile 6pack using Pelles C: - - pocc 6pack.c - pocc 6unpack.c - pocc fastlz.c - polink 6pack.obj fastlz.obj - polink 6unpack.obj fastlz.obj - -For speed optimization, always use proper compile flags for optimization options. -Typical compiler flags are given below: - -* GCC (pre 4.2): -march=pentium -O3 -fomit-frame-pointer -mtune=pentium -* GCC 4.2 or later: -march=pentium -O3 -fomit-frame-pointer -mtune=generic -* Digital Mars C/C++: -o+all -5 -* Intel C++ (Windows): /O3 /Qipo -* Intel C++ (Linux): -O2 -march=pentium -mtune=pentium -* Borland C++: -O2 -5 -* LCC-Win32: -O -* Pelles C: /O2 - diff --git a/kernel/vm/fastlz/fastlz.c b/kernel/vm/fastlz/fastlz.c deleted file mode 100644 index 3c9d6f6f..00000000 --- a/kernel/vm/fastlz/fastlz.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - FastLZ - lightning-fast lossless compression library - - Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) - Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) - Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) - -/* - * Always check for bound when decompressing. - * Generally it is best to leave it defined. - */ -#define FASTLZ_SAFE - -/* - * Give hints to the compiler for branch prediction optimization. - */ -#if defined(__GNUC__) && (__GNUC__ > 2) -#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1)) -#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0)) -#else -#define FASTLZ_EXPECT_CONDITIONAL(c) (c) -#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c) -#endif - -/* - * Use inlined functions for supported systems. - */ -#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C) -#define FASTLZ_INLINE inline -#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__) -#define FASTLZ_INLINE __inline -#else -#define FASTLZ_INLINE -#endif - -/* - * Prevent accessing more than 8-bit at once, except on x86 architectures. - */ -#if !defined(FASTLZ_STRICT_ALIGN) -#define FASTLZ_STRICT_ALIGN -#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */ -#undef FASTLZ_STRICT_ALIGN -#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */ -#undef FASTLZ_STRICT_ALIGN -#elif defined(_M_IX86) /* Intel, MSVC */ -#undef FASTLZ_STRICT_ALIGN -#elif defined(__386) -#undef FASTLZ_STRICT_ALIGN -#elif defined(_X86_) /* MinGW */ -#undef FASTLZ_STRICT_ALIGN -#elif defined(__I86__) /* Digital Mars */ -#undef FASTLZ_STRICT_ALIGN -#endif -#endif - -/* - * FIXME: use preprocessor magic to set this on different platforms! - */ -typedef unsigned char flzuint8; -typedef unsigned short flzuint16; -typedef unsigned int flzuint32; - -/* prototypes */ -int fastlz_compress(const void* input, int length, void* output); -int fastlz_compress_level(int level, const void* input, int length, void* output); -int fastlz_decompress(const void* input, int length, void* output, int maxout); - -#define MAX_COPY 32 -#define MAX_LEN 264 /* 256 + 8 */ -#define MAX_DISTANCE 8192 - -#if !defined(FASTLZ_STRICT_ALIGN) -#define FASTLZ_READU16(p) *((const flzuint16*)(p)) -#else -#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8) -#endif - -#define HASH_LOG 13 -#define HASH_SIZE (1<< HASH_LOG) -#define HASH_MASK (HASH_SIZE-1) -#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; } - -#undef FASTLZ_LEVEL -#define FASTLZ_LEVEL 1 - -#undef FASTLZ_COMPRESSOR -#undef FASTLZ_DECOMPRESSOR -#define FASTLZ_COMPRESSOR fastlz1_compress -#define FASTLZ_DECOMPRESSOR fastlz1_decompress -static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output); -static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout); -#include "fastlz.c" - -#undef FASTLZ_LEVEL -#define FASTLZ_LEVEL 2 - -#undef MAX_DISTANCE -#define MAX_DISTANCE 8191 -#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1) - -#undef FASTLZ_COMPRESSOR -#undef FASTLZ_DECOMPRESSOR -#define FASTLZ_COMPRESSOR fastlz2_compress -#define FASTLZ_DECOMPRESSOR fastlz2_decompress -static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output); -static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout); -#include "fastlz.c" - -int fastlz_compress(const void* input, int length, void* output) -{ - /* for short block, choose fastlz1 */ - if(length < 65536) - return fastlz1_compress(input, length, output); - - /* else... */ - return fastlz2_compress(input, length, output); -} - -int fastlz_decompress(const void* input, int length, void* output, int maxout) -{ - /* magic identifier for compression level */ - int level = ((*(const flzuint8*)input) >> 5) + 1; - - if(level == 1) - return fastlz1_decompress(input, length, output, maxout); - if(level == 2) - return fastlz2_decompress(input, length, output, maxout); - - /* unknown level, trigger error */ - return 0; -} - -int fastlz_compress_level(int level, const void* input, int length, void* output) -{ - if(level == 1) - return fastlz1_compress(input, length, output); - if(level == 2) - return fastlz2_compress(input, length, output); - - return 0; -} - -#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */ - -static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output) -{ - const flzuint8* ip = (const flzuint8*) input; - const flzuint8* ip_bound = ip + length - 2; - const flzuint8* ip_limit = ip + length - 12; - flzuint8* op = (flzuint8*) output; - - const flzuint8* htab[HASH_SIZE]; - const flzuint8** hslot; - flzuint32 hval; - - flzuint32 copy; - - /* sanity check */ - if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4)) - { - if(length) - { - /* create literal copy only */ - *op++ = length-1; - ip_bound++; - while(ip <= ip_bound) - *op++ = *ip++; - return length+1; - } - else - return 0; - } - - /* initializes hash table */ - for (hslot = htab; hslot < htab + HASH_SIZE; hslot++) - *hslot = ip; - - /* we start with literal copy */ - copy = 2; - *op++ = MAX_COPY-1; - *op++ = *ip++; - *op++ = *ip++; - - /* main loop */ - while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) - { - const flzuint8* ref; - flzuint32 distance; - - /* minimum match length */ - flzuint32 len = 3; - - /* comparison starting-point */ - const flzuint8* anchor = ip; - - /* check for a run */ -#if FASTLZ_LEVEL==2 - if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1)) - { - distance = 1; - ip += 3; - ref = anchor - 1 + 3; - goto match; - } -#endif - - /* find potential match */ - HASH_FUNCTION(hval,ip); - hslot = htab + hval; - ref = htab[hval]; - - /* calculate distance to the match */ - distance = anchor - ref; - - /* update hash table */ - *hslot = anchor; - - /* is this a match? check the first 3 bytes */ - if(distance==0 || -#if FASTLZ_LEVEL==1 - (distance >= MAX_DISTANCE) || -#else - (distance >= MAX_FARDISTANCE) || -#endif - *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++) - goto literal; - -#if FASTLZ_LEVEL==2 - /* far, needs at least 5-byte match */ - if(distance >= MAX_DISTANCE) - { - if(*ip++ != *ref++ || *ip++!= *ref++) - goto literal; - len += 2; - } - - match: -#endif - - /* last matched byte */ - ip = anchor + len; - - /* distance is biased */ - distance--; - - if(!distance) - { - /* zero distance means a run */ - flzuint8 x = ip[-1]; - while(ip < ip_bound) - if(*ref++ != x) break; else ip++; - } - else - for(;;) - { - /* safe because the outer check against ip limit */ - if(*ref++ != *ip++) break; - if(*ref++ != *ip++) break; - if(*ref++ != *ip++) break; - if(*ref++ != *ip++) break; - if(*ref++ != *ip++) break; - if(*ref++ != *ip++) break; - if(*ref++ != *ip++) break; - if(*ref++ != *ip++) break; - while(ip < ip_bound) - if(*ref++ != *ip++) break; - break; - } - - /* if we have copied something, adjust the copy count */ - if(copy) - /* copy is biased, '0' means 1 byte copy */ - *(op-copy-1) = copy-1; - else - /* back, to overwrite the copy count */ - op--; - - /* reset literal counter */ - copy = 0; - - /* length is biased, '1' means a match of 3 bytes */ - ip -= 3; - len = ip - anchor; - - /* encode the match */ -#if FASTLZ_LEVEL==2 - if(distance < MAX_DISTANCE) - { - if(len < 7) - { - *op++ = (len << 5) + (distance >> 8); - *op++ = (distance & 255); - } - else - { - *op++ = (7 << 5) + (distance >> 8); - for(len-=7; len >= 255; len-= 255) - *op++ = 255; - *op++ = len; - *op++ = (distance & 255); - } - } - else - { - /* far away, but not yet in the another galaxy... */ - if(len < 7) - { - distance -= MAX_DISTANCE; - *op++ = (len << 5) + 31; - *op++ = 255; - *op++ = distance >> 8; - *op++ = distance & 255; - } - else - { - distance -= MAX_DISTANCE; - *op++ = (7 << 5) + 31; - for(len-=7; len >= 255; len-= 255) - *op++ = 255; - *op++ = len; - *op++ = 255; - *op++ = distance >> 8; - *op++ = distance & 255; - } - } -#else - - if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2)) - while(len > MAX_LEN-2) - { - *op++ = (7 << 5) + (distance >> 8); - *op++ = MAX_LEN - 2 - 7 -2; - *op++ = (distance & 255); - len -= MAX_LEN-2; - } - - if(len < 7) - { - *op++ = (len << 5) + (distance >> 8); - *op++ = (distance & 255); - } - else - { - *op++ = (7 << 5) + (distance >> 8); - *op++ = len - 7; - *op++ = (distance & 255); - } -#endif - - /* update the hash at match boundary */ - HASH_FUNCTION(hval,ip); - htab[hval] = ip++; - HASH_FUNCTION(hval,ip); - htab[hval] = ip++; - - /* assuming literal copy */ - *op++ = MAX_COPY-1; - - continue; - - literal: - *op++ = *anchor++; - ip = anchor; - copy++; - if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) - { - copy = 0; - *op++ = MAX_COPY-1; - } - } - - /* left-over as literal copy */ - ip_bound++; - while(ip <= ip_bound) - { - *op++ = *ip++; - copy++; - if(copy == MAX_COPY) - { - copy = 0; - *op++ = MAX_COPY-1; - } - } - - /* if we have copied something, adjust the copy length */ - if(copy) - *(op-copy-1) = copy-1; - else - op--; - -#if FASTLZ_LEVEL==2 - /* marker for fastlz2 */ - *(flzuint8*)output |= (1 << 5); -#endif - - return op - (flzuint8*)output; -} - -static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout) -{ - const flzuint8* ip = (const flzuint8*) input; - const flzuint8* ip_limit = ip + length; - flzuint8* op = (flzuint8*) output; - flzuint8* op_limit = op + maxout; - flzuint32 ctrl = (*ip++) & 31; - int loop = 1; - - do - { - const flzuint8* ref = op; - flzuint32 len = ctrl >> 5; - flzuint32 ofs = (ctrl & 31) << 8; - - if(ctrl >= 32) - { -#if FASTLZ_LEVEL==2 - flzuint8 code; -#endif - len--; - ref -= ofs; - if (len == 7-1) -#if FASTLZ_LEVEL==1 - len += *ip++; - ref -= *ip++; -#else - do - { - code = *ip++; - len += code; - } while (code==255); - code = *ip++; - ref -= code; - - /* match from 16-bit distance */ - if(FASTLZ_UNEXPECT_CONDITIONAL(code==255)) - if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8))) - { - ofs = (*ip++) << 8; - ofs += *ip++; - ref = op - ofs - MAX_DISTANCE; - } -#endif - -#ifdef FASTLZ_SAFE - if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit)) - return 0; - - if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output)) - return 0; -#endif - - if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) - ctrl = *ip++; - else - loop = 0; - - if(ref == op) - { - /* optimize copy for a run */ - flzuint8 b = ref[-1]; - *op++ = b; - *op++ = b; - *op++ = b; - for(; len; --len) - *op++ = b; - } - else - { -#if !defined(FASTLZ_STRICT_ALIGN) - const flzuint16* p; - flzuint16* q; -#endif - /* copy from reference */ - ref--; - *op++ = *ref++; - *op++ = *ref++; - *op++ = *ref++; - -#if !defined(FASTLZ_STRICT_ALIGN) - /* copy a byte, so that now it's word aligned */ - if(len & 1) - { - *op++ = *ref++; - len--; - } - - /* copy 16-bit at once */ - q = (flzuint16*) op; - op += len; - p = (const flzuint16*) ref; - for(len>>=1; len > 4; len-=4) - { - *q++ = *p++; - *q++ = *p++; - *q++ = *p++; - *q++ = *p++; - } - for(; len; --len) - *q++ = *p++; -#else - for(; len; --len) - *op++ = *ref++; -#endif - } - } - else - { - ctrl++; -#ifdef FASTLZ_SAFE - if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit)) - return 0; - if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit)) - return 0; -#endif - - *op++ = *ip++; - for(--ctrl; ctrl; ctrl--) - *op++ = *ip++; - - loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit); - if(loop) - ctrl = *ip++; - } - } - while(FASTLZ_EXPECT_CONDITIONAL(loop)); - - return op - (flzuint8*)output; -} - -#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */ diff --git a/kernel/vm/fastlz/fastlz.h b/kernel/vm/fastlz/fastlz.h deleted file mode 100644 index f87bc7be..00000000 --- a/kernel/vm/fastlz/fastlz.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - FastLZ - lightning-fast lossless compression library - - Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) - Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) - Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef FASTLZ_H -#define FASTLZ_H - -#define FASTLZ_VERSION 0x000100 - -#define FASTLZ_VERSION_MAJOR 0 -#define FASTLZ_VERSION_MINOR 0 -#define FASTLZ_VERSION_REVISION 0 - -#define FASTLZ_VERSION_STRING "0.1.0" - -#if defined (__cplusplus) -extern "C" { -#endif - -/** - Compress a block of data in the input buffer and returns the size of - compressed block. The size of input buffer is specified by length. The - minimum input buffer size is 16. - - The output buffer must be at least 5% larger than the input buffer - and can not be smaller than 66 bytes. - - If the input is not compressible, the return value might be larger than - length (input buffer size). - - The input buffer and the output buffer can not overlap. -*/ - -int fastlz_compress(const void* input, int length, void* output); - -/** - Decompress a block of compressed data and returns the size of the - decompressed block. If error occurs, e.g. the compressed data is - corrupted or the output buffer is not large enough, then 0 (zero) - will be returned instead. - - The input buffer and the output buffer can not overlap. - - Decompression is memory safe and guaranteed not to write the output buffer - more than what is specified in maxout. - */ - -int fastlz_decompress(const void* input, int length, void* output, int maxout); - -/** - Compress a block of data in the input buffer and returns the size of - compressed block. The size of input buffer is specified by length. The - minimum input buffer size is 16. - - The output buffer must be at least 5% larger than the input buffer - and can not be smaller than 66 bytes. - - If the input is not compressible, the return value might be larger than - length (input buffer size). - - The input buffer and the output buffer can not overlap. - - Compression level can be specified in parameter level. At the moment, - only level 1 and level 2 are supported. - Level 1 is the fastest compression and generally useful for short data. - Level 2 is slightly slower but it gives better compression ratio. - - Note that the compressed data, regardless of the level, can always be - decompressed using the function fastlz_decompress above. -*/ - -int fastlz_compress_level(int level, const void* input, int length, void* output); - -#if defined (__cplusplus) -} -#endif - -#endif /* FASTLZ_H */ diff --git a/kernel/vm/frame.c b/kernel/vm/frame.c deleted file mode 100644 index 37616303..00000000 --- a/kernel/vm/frame.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "vm.h" -//#include "frame.h" -#include "klibc.h" - -struct vm_free_frame -{ - void *next; // Next free frame -}; - -struct vm_free_frame *vm_free_list = 0x0; - -int vm_build_free_frame_list(void *start, void *end) -{ - vm_free_list = start; - struct vm_free_frame *p = start; - for (p = start; (void*) p < end; p = (void*) p + BLOCK_SIZE) - { - p->next = (void*) p + BLOCK_SIZE; - if ((unsigned int) ((void*) p + BLOCK_SIZE) >= (unsigned int) end) - { - p->next = 0x0; - } - } - return 0; -} - -void *vm_get_free_frame() -{ - // Check if there are no frames - if (vm_free_list == 0x0) - { - return 0x0; - } - void *p = vm_free_list; - vm_free_list = vm_free_list->next; - return p - 0xf0000000; // Convert from VPTR to PPTR -} - -void vm_release_frame(void *p) -{ - // TODO: Check if p is actually a valid frame - p += 0xf0000000; // Convert from PPTR to VPTR - struct vm_free_frame *flist = p; - flist->next = vm_free_list; - os_printf("%X %X\n", flist, vm_free_list); - vm_free_list = p; -} - -int vm_count_free_frames() -{ - int cnt = 0; - struct vm_free_frame *p = vm_free_list; - while ((p = p->next)) - { - if (p == p->next) - { - ERROR("Fatal problem: The free frame list has a cycle.\n"); - return -1; - } - cnt++; - } - return cnt; -} diff --git a/kernel/vm/frame.h b/kernel/vm/frame.h deleted file mode 100644 index 87f00fa5..00000000 --- a/kernel/vm/frame.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __VM_FRAME_H -#define __VM_FRAME_H - -int vm_build_free_frame_list(void *start, void *end); -void *vm_get_free_frame(); -void vm_release_frame(void *p); -int vm_count_free_frames(); - -#endif diff --git a/kernel/vm/memory-layout.svg b/kernel/vm/memory-layout.svg deleted file mode 100644 index a6b75dc4..00000000 --- a/kernel/vm/memory-layout.svg +++ /dev/null @@ -1,652 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - Physical Memory - - Kernel - 0x0 - 0x10000 - 0x200000 - - L1PTBASE - 0x300000 - - 0x7F00000 - VirtualMemoryFrames(128MB) - KDS - 0x7FFFFFF - (Interrupt Vectors) - Virtual Memory (Reserved) - - - Kernel - 0x10000 - 0x200000 - - 0x7F00000 - KDS - 0x7FFFFFF - (Interrupt Vectors) - - L1PTBASE - 0xF0200000 - - 0xF0300000 - - Kernel - - 0xF0000000 - - 0xFFF00000 - KDS - 0xFFFFFFFF - Peripherals - - - 0x10000000 - 0x10200000 - - diff --git a/kernel/vm/swap_framework.c b/kernel/vm/swap_framework.c deleted file mode 100644 index 7fd9db76..00000000 --- a/kernel/vm/swap_framework.c +++ /dev/null @@ -1,259 +0,0 @@ -#include "vm.h" -#include "memory.h" -#include "klibc.h" -#include -#include "swap_framework.h" -#include "swap_pqueue.h" -#include "swap_fs.h" -#include "fastlz/fastlz.h" - -// NOTE: SWAPPING CANNOT WORK UNTIL FILESYSTEMS CAN ALLOCATE MORE THAN 16 PAGES AT A TIME -void swap_init() -{ - // initialize a swap space struct to hold values to then pass - // TODO: change to guarantee allocation in RAM - holder = (struct swap_space*) kmalloc(sizeof(struct swap_space)); -} - -// INCOMPLETE -uint32_t store_page_LZ(void *page, uint32_t *ID) -{ - struct node *LZ_swap = (struct node*) pqueue_peek(2); - - // allocate this on RAM this is where you os_memcpy the given page!! - // NOTE: THAT 1.05 DOESN'T MULTIPLY TO A CLEAN NUMBER - void *e_page = kmalloc(PAGE_SIZE * 1.05); // output buffer needs to be at least 5% bigger than input - - int32_t cmp_size; - cmp_size = fastlz_compress(page, PAGE_SIZE, e_page); - - /*if compressed size is greater than uncompressed size, input may not be - compressible; return error */ - if (cmp_size > PAGE_SIZE) - { - return 0; - } - - struct swap_entry *curr_ent = LZ_swap->e_head; - int i = 0; - while (curr_ent->cmp_page != NULL) - { - curr_ent += sizeof(struct swap_entry); - i++; - } - *ID = i; - curr_ent->cmp_size = cmp_size; - curr_ent->e_flags = 1; //NOT CORRECT, put wherever it comes from here - struct vas *kvas = KERNEL_VAS; - int curr_add = 0x200000; - - // loop until free physical memory frame is found - while (vm_allocate_page(kvas, curr_add, 4) == 0) - { - curr_add += PAGE_SIZE; - } - - // after deciding physical memory location, store physical memory location in cmp_page - curr_ent->cmp_page = curr_add; - kfree(e_page); // after copying over relevant bits of cmp data in this oversized buffer - if (curr_ent->cmp_page != NULL) - { - curr_ent += sizeof(struct swap_entry); - curr_ent = (struct swap_entry*) kmalloc(sizeof(struct swap_entry)); - } - memory_count += 4096; - return *ID; -} - -uint32_t store_page(void *page, uint32_t *ID) -{ - uint8_t lowbits = *((uint32_t*) page) & 0x000000FF; - if (swapfs_store(page, ID, lowbits) == -1) - { - return 0; - } - memory_count += 4096; - return *ID; -} - -// INCOMPLETE -uint32_t retrieve_page_LZ(void *page, uint32_t *ID) -{ - struct node *lz_swap = (struct node*) pqueue_peek(2); - struct swap_entry *curr_ent = lz_swap->e_head; - for (int i = 0; i < *ID; i++) - { - curr_ent += sizeof(struct swap_entry); - } - void *uncomp_page = kmalloc(PAGE_SIZE); - int uncomp_size = fastlz_decompress(curr_ent->cmp_page, /*constant?*/ - COMPRESSED_SIZE / PAGE_ENTRIES, uncomp_page, PAGE_SIZE); - - /* if uncompressed size is not the size of a page or is 0 - (indicating corrupted data or a too small output buffer (the latter of - which should never happen)), returns error */ - if (uncomp_size != PAGE_SIZE || uncomp_size == 0) - { - return 0; - } - // place the decompressed page back into memory. - os_memcpy(page, uncomp_page, PAGE_SIZE); - kfree(uncomp_page); - struct vas* kvas = KERNEL_VAS; - vm_free_page(kvas, curr_ent->cmp_page); - curr_ent->e_flags = 0; - curr_ent->cmp_page = NULL; - memory_count -= 4096; - return *ID; -} - -uint32_t retrieve_page(void *page, uint32_t *ID) -{ - uint8_t lowbits = *((uint32_t*) page) & 0x000000FF; -// if (swapfs_retrieve(page, ID, lowbits) == -1) { // GIVES ERROR FOR SOME REASON?? -// return 0; -// } - memory_count -= 4096; - return *ID; -} - -os_size_t sum_stored() -{ - return memory_count; -} - -uint32_t vm_swapin_page(void *page, uint32_t *ID) -{ - struct node *swap_area; - uint8_t ssid = *((uint32_t*) page) & 0x000000FF; -// uint32_t sse = *((uint32_t*)page) & 0xFFFFFF00; - - // check if swap space exists - if ((swap_area = pqueue_find(ssid)) == NULL) - { - /// check if there's enough memory for LZ compression - // NOTE: always false until store/retrieve_page_LZ works - if (0/*vm_count_free_frames() > COMPRESSED_SIZE/PAGE_ENTRIES*/) - { - vm_register_swap_space(store_page_LZ, retrieve_page_LZ, 0, -1); - swap_area = pqueue_find(-1); - } - else - { - vm_register_swap_space(store_page, retrieve_page, 1, ssid); - swap_area = pqueue_find(ssid); - } - } - - return swap_area->store_func(page, ID); -} - -uint32_t vm_swapout_page(void *page, uint32_t *ID) -{ - uint8_t ssid = *((uint32_t*) page) & 0x000000FF; - struct node *swap_area = pqueue_find(ssid); - return swap_area->retrieve_func(page, ID); -} - -int vm_register_swap_space(func store_p, func retrieve_p, int priority, - int16_t ssid) -{ - /* waiting on fs team to increase 16 page limit, parameters - SHOULD be (PAGE_ENTRIES, ssid) or (sse, ssid) */ - - if (priority == 1) - { - swapfs_init(PAGE_ENTRIES, ssid); - holder->e_head = NULL; - } - if (priority == 0) - { - if (holder->e_head = (struct swap_entry*) kmalloc( - sizeof(struct swap_entry)) == NULL) - { - return -1; - } -// holder->e_head->next = NULL; - holder->e_head->e_flags = 0; - holder->e_head->cmp_page = NULL; - } - holder->lower_bits = ssid; - holder->priority = priority; - holder->store_func = store_p; - holder->retrieve_func = retrieve_p; - pqueue_push(holder); - return 1; -} - -void vm_deregister_swap_space(uint8_t ssid) -{ - pqueue_pop_at(ssid); -} - -uint32_t vm_page_fault(void *page) -{ - /* TODO: - * check if memory is full and needs to evict a page from RAM - * figure out which page to evict than evict that page - * page in the new page (done.) - */ - - //TODO: eventually change from equaling page to an actual id by establishing a proper hash table - uint32_t* id = (uint32_t*) page; - - int temp; - if ((temp = vm_swap_free_mapping(KERNEL_VAS, page, id)) < 0) - { - if (temp == VM_ERR_BADV) - { - os_printf("Virtual pointer passed was invalid [page_fault]"); - } - if (temp == VM_ERR_NOT_MAPPED) - { - os_printf( - "Virtual pointer was not mapped using set_mapping [page_fault]"); - } - return 0; - } - - uint8_t ssid = *((uint32_t*) page) & 0x000000FF; - uint32_t ss_entry = *((uint32_t*) page) & 0xFFFFFF00; - struct node *swap_area = pqueue_find(ssid); - // load memory back into RAM - swap_area->retrieve_func(page, &ss_entry); - - // find a free frame to map - void *pptr = vm_get_free_frame(); - // TODO: once hashtable is properly set change permission to proper value - int perm = VM_PERM_USER_RW; - if (vm_set_mapping(KERNEL_VAS, page, pptr, perm) < 0) - { - if (temp == VM_ERR_BADV) - { - os_printf("Virtual pointer passed was invalid [page_fault]"); - } - if (temp == VM_ERR_BADP) - { - os_printf("Physical pointer passed was invalid [page_fault]"); - } - if (temp == VM_ERR_MAPPED) - { - os_printf( - "The virtual pointer passed has already been mapped [page_fault]"); - } - return 0; - } - // Get level 2 page table - uint32_t *l2pt = (uint32_t*) VM_ENTRY_GET_L2( - (uint32_t) VM_L1_GET_ENTRY(vm_get_current_vas()->l1_pagetable, - page)); - - // confirm from @lkolby whether this will work for setting the page table - uint32_t *tmp = (uint32_t*) VM_L2_ENTRY(l2pt, page); - *tmp = (uint32_t*) page; - - return *((uint32_t*) pptr); -} - -//uint32_t* vm_scan_pages(void *page, uint32_t *ID); - diff --git a/kernel/vm/swap_fs.c b/kernel/vm/swap_fs.c deleted file mode 100644 index 74604d66..00000000 --- a/kernel/vm/swap_fs.c +++ /dev/null @@ -1,161 +0,0 @@ -#include "file.h" -#include "bitvector.h" -#include "vm.h" -#include "klibc.h" -#include "swap_fs.h" - -char *generate_filename(uint8_t ssid) -{ - char *output; - if (ssid < 10) - { // single digit - char swapfile[9] = - { '/', 's', 'w', 'a', 'p', '0', '0', ssid + 48, 0 }; - output = swapfile; - } - else if (ssid < 100) - { // double digit - int tmp = ssid / 10; - char swapfile[9] = - { '/', 's', 'w', 'a', 'p', '0', tmp + 48, (ssid % 10) + 48, 0 }; - output = swapfile; - } - else - { // triple digit - int tmp = ssid / 10; - int tmp2 = ssid / 100; - char swapfile[9] = - { '/', 's', 'w', 'a', 'p', tmp2 + 48, tmp + 48, ssid + 48, 0 }; - output = swapfile; - } - return output; -} - -int32_t swapfs_init(int npages, uint8_t ssid) -{ - int fd; - int nbytes; - // Initialize the free bitmap -// free_bitvector = make_vector(npages); - bv_arr[ssid] = make_vector(npages); - - // making new files instead of a tree b/c the FS can't do it - char *swapfile = generate_filename(ssid); - - // The permissions parameter doesn't quite work right now (BUG?) - if (kcreate(swapfile, 'w', 1) < 0) - { - return -1; - } - - // For now, we have to fill the file with that much blank storage. - if ((fd = kopen(swapfile, 'w')) < 0) - { - return -1; - } - void *empty_page = kmalloc(BLOCK_SIZE); - - // seems useless to me...? - for (int i = 0; i < npages; i++) - { - if ((nbytes = kwrite(fd, empty_page, BLOCK_SIZE)) < 0) - { - return -1; - } - } - - kfree(empty_page); - kclose(fd); - - return nbytes * npages; // success -} - -int64_t swapfs_store(void *page, uint32_t *id, uint8_t ssid) -{ - int32_t fd; - char *swapfile; - int32_t b; - // Get the index to store the page into - *id = *((uint32_t*) page) & 0xFFFFFF00; - - if ((b = bv_isfree(*id, bv_arr[ssid])) <= 0) - { - if (b == -1) - { - os_printf("invalid index [swapfs_store]"); - } - else - { - os_printf("index not free [swapfs_store]"); - } - - return -1; - } - - // Error if invalid index - if (bv_set(*id, bv_arr[ssid]) < 0) - { - return -1; - } - - swapfile = generate_filename(ssid); - // Error if failed to open - if ((fd = kopen(swapfile, 'w')) < 0) - { - return -1; - } - - // Error if seeks beyond boundaries - if (kseek(fd, (*id) * BLOCK_SIZE) < 0) - { - return -1; - } - - if (kwrite(fd, page, BLOCK_SIZE) < 0) - { - return -1; - } - kclose(fd); - - return *id; // success -} - -int64_t swapfs_retreive(void *page, uint32_t *id, uint8_t ssid) -{ - int fd; - char *swapfile; - //checks if index is free - if (!bv_get(*id, bv_arr[ssid])) - { - return -1; - } - - swapfile = generate_filename(ssid); - - // not sure if I should make the index free here... - bv_lower(*id, bv_arr[ssid]); - - if ((fd = kopen(swapfile, 'r')) < 0) - { - return -1; - } - - kseek(fd, (*id) * BLOCK_SIZE); - kread(fd, page, BLOCK_SIZE); - kclose(fd); - - return 1; // success -} - -int32_t swapfs_disable(uint8_t ssid) -{ - char *swapfile; - bv_free(bv_arr[ssid]); - swapfile = generate_filename(ssid); - if (kdelete(swapfile, 0) < 0) - { - return -1; - } - - return 1; // success -} diff --git a/kernel/vm/vm.c b/kernel/vm/vm.c deleted file mode 100644 index 3be3b78c..00000000 --- a/kernel/vm/vm.c +++ /dev/null @@ -1,464 +0,0 @@ -#include "vm.h" -#include "memory.h" -#include "klibc.h" -#include "frame.h" - -#define CHECK_VPTR if ((unsigned int)vptr & (BLOCK_SIZE-1)) return VM_ERR_BADV; -#define CHECK_PPTR if ((unsigned int)pptr & (BLOCK_SIZE-1)) return VM_ERR_BADP; - -static const int perm_mapping[16] = -{ 0, // 0000 Nothing - 5, // 0001 Privileged RO, nothing otherwise - 6, // 0010 User RO, privileged RO. - 6, // 0011 User RO, privileged RO. - 1, // 0100 Privileged RW, nothing otherwise - -1, // 0101 ??? - 2, // 0110 Privileged RW, user RO - -1, // 0111 ??? - 3, // 1000 User RW, privileged RW - -1, // 1001 ??? - -1, // 1010 ??? - -1, // 1011 ??? - 3, // 1100 User RW, privileged RW - -1, // 1101 ??? - -1, // 1110 ??? - -1, // 1111 ??? - }; - -static struct vas *vm_current_vas = (struct vas*) V_L1PTBASE; - -struct vm_free_list -{ - struct vm_free_list *next; -}; - -struct vm_free_list *vm_vas_free_list = 0x0; -struct vm_free_list *vm_l1pt_free_list = 0x0; -struct vm_free_list *vm_l2pt_free_list = 0x0; - -void vm_init() -{ - // Initialize the VAS structures. We allocate enough for 4096 VASs. - struct vm_free_list *free_vas = (struct vm_free_list*) P_L1PTBASE; - //vm_vas_free_list = free_vas; - vm_vas_free_list = (struct vm_free_list*) ((void*) free_vas + V_L1PTBASE - - P_L1PTBASE); - struct vm_free_list *last = 0x0; - while ((uint32_t) free_vas < P_L1PTBASE + sizeof(struct vas) * 4096) - { - free_vas->next = 0x0; - if (last) - { - last->next = (struct vm_free_list*) ((void*) free_vas + V_L1PTBASE - - P_L1PTBASE); - } - last = free_vas; - free_vas = - (struct vm_free_list*) ((void*) free_vas + sizeof(struct vas)); - } - - // Initialize the L1 page tables - struct vm_free_list *free_l1pt = (struct vm_free_list*) (P_L1PTBASE - + sizeof(struct vas) * 4096); - vm_l1pt_free_list = (struct vm_free_list*) ((void*) free_l1pt + V_L1PTBASE - - P_L1PTBASE); - last = 0x0; - while ((uint32_t) free_l1pt < P_L1PTBASE + (1 << 20) - ((1 << 20) >> 2)) - { - free_l1pt->next = 0x0; - if (last) - { - last->next = (struct vm_free_list*) ((void*) free_l1pt + V_L1PTBASE - - P_L1PTBASE); - } - last = free_l1pt; - free_l1pt = - (struct vm_free_list*) ((void*) free_l1pt + PAGE_TABLE_SIZE); - } - - // Initialize the L2 coarse page tables - struct vm_free_list *free_l2pt = (struct vm_free_list*) (P_L1PTBASE - + (1 << 19)); - vm_l2pt_free_list = (struct vm_free_list*) ((void*) free_l2pt + V_L1PTBASE - - P_L1PTBASE); - last = 0x0; - while ((uint32_t) free_l2pt < P_L1PTBASE + (1 << 20)) - { - free_l2pt->next = 0x0; - if (last) - { - last->next = (struct vm_free_list*) ((void*) free_l2pt + V_L1PTBASE - - P_L1PTBASE); - } - last = free_l2pt; - free_l2pt = (struct vm_free_list*) ((void*) free_l2pt - + L2_PAGE_TABLE_SIZE); - } -} - -uint32_t *vm_alloc_coarse_page_table() -{ - // TODO: What if we run out? - uint32_t *vptr = (uint32_t*) vm_l2pt_free_list; - if (vptr == 0x0) - { - LOG( - "Could not allocate a coarse page table, bad things will happen soon.\n"); - return NULL; - } - vm_l2pt_free_list = ((struct vm_free_list*) vptr)->next; - os_memset((void*) vptr, 0, L2_PAGE_TABLE_SIZE); - return vptr; -} - -uint32_t *vm_vtop(struct vas *vas, uint32_t *vptr) -{ - // Hack. Assume it's all linearly mapped, and vas == KERNEL_VAS - if (vas != KERNEL_VAS) - { - os_printf("vas is not KERNEL_VAS in vm_vtop. :-(\n"); - while (1) - ; - } - return (uint32_t*) ((void*) vptr - V_L1PTBASE + P_L1PTBASE); -} - -uint32_t *vm_ptov(struct vas *vas, uint32_t *vptr) -{ - // Hack. Assume it's all linearly mapped, and vas == KERNEL_VAS - if (vas != KERNEL_VAS) - { - os_printf("vas is not KERNEL_VAS in vm_vtop. :-(\n"); - while (1) - ; - } - return (uint32_t*) ((void*) vptr + V_L1PTBASE - P_L1PTBASE); -} - -struct vas *vm_get_current_vas() -{ - return vm_current_vas; -} - -void vm_use_kernel_vas() -{ - vm_enable_vas((struct vas*) V_L1PTBASE); -} - -int vm_allocate_page(struct vas *vas, void *vptr, int permission) -{ - CHECK_VPTR; - - // We have to save the current VAS and switch to the kernel VAS - struct vas *prev_vas = vm_current_vas; - vm_use_kernel_vas(); - - // TODO: Check if the vas already has a mapping there. - void *pptr = vm_get_free_frame(); - if (pptr == 0x0) - { - // We need to swap! (or something...) - vm_enable_vas(prev_vas); - return VM_ERR_UNKNOWN; // For now, just fail - } - - os_printf("mapping VA %x to PA %x\n", vptr, pptr); - - //LOG("Free frame is at: %X\n", pptr); - int retval = vm_set_mapping(vas, vptr, pptr, permission); - if (retval) - { - // Release the frame to prevent a memory leak - os_printf("vm_set_mapping returned %d for 0x%X\n", retval, vptr); - vm_release_frame(pptr); - vm_enable_vas(prev_vas); - return retval; - } - - vm_enable_vas(prev_vas); - return 0; -} - -void *vm_allocate_pages(struct vas *vas, void *vptr, uint32_t nbytes, - int permission) -{ - int rc; - unsigned char *p = (unsigned char*) vptr; - while (p - (unsigned char*) vptr < nbytes) - { - rc = vm_allocate_page(vas, p, permission); - assert(rc == 0); - p += BLOCK_SIZE; - } - return p; -} - -#define VM_L1_GET_ENTRY(table,vptr) table[((unsigned int)vptr)>>20] -#define VM_L1_SET_ENTRY(table,vptr,ent) (table[((unsigned int)vptr)>>20]=ent) -#define VM_ENTRY_GET_FRAME(x) ((x)&~((PAGE_TABLE_SIZE<<1) - 1)) -#define VM_ENTRY_GET_L2(x) ((x)&~0x1FF) -#define VM_L2_ENTRY(l2pt,vptr) ((uint32_t*)l2pt)[((unsigned int)vptr&0x000FF000)>>12] -#define VM_L2ENTRY_GET_FRAME(x) ((x)&0xFFFFF000) - -int vm_free_page(struct vas *vas, void *vptr) -{ - CHECK_VPTR; - - // We have to save the current VAS - struct vas *prev_vas = vm_current_vas; - vm_use_kernel_vas(); - - // TODO: Check if it was actually allocated - uint32_t entry = VM_L1_GET_ENTRY(vas->l1_pagetable, vptr); - - // Okay, it's a 4KB page. We need to walk the l2 page table. - uint32_t *l2pt = vm_ptov(KERNEL_VAS, (uint32_t*) VM_ENTRY_GET_L2(entry)); - entry = VM_L2_ENTRY(l2pt, vptr); - vm_release_frame((void*) VM_L2ENTRY_GET_FRAME(entry)); - //LOG("Releasing frame %X, l2pt=%X\n", VM_L2ENTRY_GET_FRAME(entry), l2pt); - VM_L2_ENTRY(l2pt,vptr)= 0; - //vas->l1_pagetable[(unsigned int)vptr>>20] = 0; - - vm_enable_vas(prev_vas); - return 0; -} - -int vm_pin(struct vas *vas, void *vptr) -{ - // FIXME: unimplemented - return 0; -} - -int vm_unpin(struct vas *vas, void *vptr) -{ - // FIXME: unimplemented - return 0; -} - -int vm_set_mapping(struct vas *vas, void *vptr, void *pptr, int permission) -{ - CHECK_VPTR; - CHECK_PPTR; - int perm = perm_mapping[permission]; - if (perm == -1) - return VM_ERR_BADPERM; - - uint32_t cur_entry = vas->l1_pagetable[(unsigned int) vptr >> 20]; - if ((cur_entry & 3) == 2) - { - return VM_ERR_MAPPED; - } - if ((cur_entry & 3) == 0) - { - // We need to allocate a coarse page table - uint32_t *vptr_coarse_pt = vm_alloc_coarse_page_table(); - vas->l1_pagetable[(unsigned int) vptr >> 20] = (uint32_t) vm_vtop( - KERNEL_VAS, vptr_coarse_pt) | 1; - cur_entry = vas->l1_pagetable[(unsigned int) vptr >> 20]; - } - - uint32_t *l2_pagetable = vm_ptov(KERNEL_VAS, - (uint32_t*) VM_ENTRY_GET_L2(cur_entry)); - int l2_idx = ((unsigned int) vptr & 0x000FF000) >> 12; - if (l2_pagetable[l2_idx]) - { - return VM_ERR_MAPPED; - } - - //perm &= ~(1<<10); // Clear AP[0] so we get an access exception. - //vas->l1_pagetable[(unsigned int)vptr>>20] = (unsigned int)pptr | (perm<<10) | 2; - // TODO: Permissions! - int lvl2_perm = perm; //perm_mapping[perm]; - int apx_bit = (lvl2_perm & 4) >> 2; - int ap_bits = lvl2_perm & 3; - l2_pagetable[l2_idx] = (unsigned int) pptr | (apx_bit << 9) | (ap_bits << 4) - | 2; - //os_printf("pptr: %X, idx=%d, l2pt=%X\n", pptr, l2_idx, l2_pagetable); - //os_printf("permission=%d lvl2_perm=%X apx=%X ap=%X\n", permission, lvl2_perm, apx_bit, ap_bits); - //l2_pagetable[l2_idx] = (unsigned int)pptr | (1<<4) | 2; - return 0; -} - -int vm_swap_free_mapping(struct vas *vas, void *vptr, uint32_t *ID) -{ - CHECK_VPTR; - // TODO: If this is a paged frame, then we need to throw an error - if ((vas->l1_pagetable[(unsigned int) vptr >> 20] & 3) == 2) - { - vas->l1_pagetable[(unsigned int) vptr >> 20] = 0; - } - else if ((vas->l1_pagetable[(unsigned int) vptr >> 20] & 3) == 1) - { - // We have to free the mapping in the L2 page table - uint32_t *l2pt = vm_ptov(KERNEL_VAS, - (uint32_t*) VM_ENTRY_GET_L2( - vas->l1_pagetable[(unsigned int )vptr >> 20])); - VM_L2_ENTRY(l2pt, vptr)= (uint32_t) ID; - } - return 0; -} - -int vm_free_mapping(struct vas *vas, void *vptr) -{ - CHECK_VPTR; - // TODO: If this is a paged frame, then we need to throw an error - if ((vas->l1_pagetable[(unsigned int) vptr >> 20] & 3) == 2) - { - vas->l1_pagetable[(unsigned int) vptr >> 20] = 0; - } - else if ((vas->l1_pagetable[(unsigned int) vptr >> 20] & 3) == 1) - { - // We have to free the mapping in the L2 page table - uint32_t *l2pt = vm_ptov(KERNEL_VAS, - (uint32_t*) VM_ENTRY_GET_L2( - vas->l1_pagetable[(unsigned int )vptr >> 20])); - VM_L2_ENTRY(l2pt, vptr)= 0; - } - return 0; -} - -// We're going to have to switch to the kernel's VAS, then copy it over. -int vm_map_shared_memory(struct vas *vas, void *this_ptr, struct vas *other_vas, - void *other_ptr, int permission) -{ - if ((unsigned int) this_ptr & (BLOCK_SIZE - 1)) - return VM_ERR_BADV; - if ((unsigned int) other_ptr & (BLOCK_SIZE - 1)) - return VM_ERR_BADP; - - struct vas *prev_vas = vm_current_vas; - vm_enable_vas(KERNEL_VAS); - - if ((vas->l1_pagetable[(unsigned int) this_ptr >> 20] & 3) == 2) - { - return VM_ERR_MAPPED; - } - if (!other_vas->l1_pagetable[(unsigned int) other_ptr >> 20]) - { - return VM_ERR_NOT_MAPPED; - } - if (!vas->l1_pagetable[(unsigned int) this_ptr >> 20]) - { - // We need to allocate a coarse page table... - uint32_t *vptr_coarse_pt = vm_alloc_coarse_page_table(); - vas->l1_pagetable[(unsigned int) this_ptr >> 20] = (uint32_t) vm_vtop( - KERNEL_VAS, vptr_coarse_pt) | 1; - //LOG("Allocated coarse page table.\n"); - //LOG("Should be zero: %X (%X)\n", vptr_coarse_pt[0], vptr_coarse_pt); - } - uint32_t *this_l2pt = vm_ptov(KERNEL_VAS, - (uint32_t*) VM_ENTRY_GET_L2( - vas->l1_pagetable[(unsigned int )this_ptr >> 20])); - if (VM_L2_ENTRY(this_l2pt, this_ptr)) - { - //LOG("Should be zero: %X (this_l2pt=%X, idx=%d)\n", VM_L2_ENTRY(this_l2pt, this_ptr), this_l2pt, ((unsigned int)this_ptr&0x000FF000)>>12); - return VM_ERR_MAPPED; - } - uint32_t *other_l2pt = vm_ptov(KERNEL_VAS, - (uint32_t*) VM_ENTRY_GET_L2( - other_vas->l1_pagetable[(unsigned int )other_ptr >> 20])); - if (!VM_L2_ENTRY(other_l2pt, other_ptr)) - { - return VM_ERR_NOT_MAPPED; - } - - int perm = perm_mapping[permission]; - if (perm == -1) - return VM_ERR_BADPERM; - - // Well, this was remarkably easy. - //unsigned int pptr = VM_ENTRY_GET_FRAME(other_vas->l1_pagetable[(unsigned int)other_ptr>>20]); - unsigned int pptr = VM_L2ENTRY_GET_FRAME( - VM_L2_ENTRY(other_l2pt, other_ptr)); - //os_printf("pptr: %X\n",pptr); - //perm &= ~(1<<10); // Clear AP[0] so we get an access exception. - //vas->l1_pagetable[(unsigned int)this_ptr>>20] = pptr | (perm<<10) | 2; - VM_L2_ENTRY(this_l2pt, this_ptr)= pptr | (1<<4) | 2; - LOG("%X\n", VM_L2_ENTRY(this_l2pt, this_ptr)); - - vm_enable_vas(prev_vas); - return 0; -} - -void vm_enable_vas(struct vas *vas) -{ - vm_current_vas = vas; - - // Clear the BTAC - // Performed by cleaning the caches, below - // asm volatile("mcr p15, 0, %[r], c7, c5, 6" : : [r] "r" (0x0)); - - // Flush the write caches - asm volatile("MCR p15, 0, %[r], c7, c10, 4" : : [r] "r" (0x0)); - // sync barrier - asm volatile("MCR p15, 0, %[r], c7, c10, 5" : : [r] "r" (0x0)); - // memory barrier - - //TTBR0 - asm volatile("mcr p15, 0, %[addr], c2, c0, 0" : : [addr] "r" (vas->l1_pagetable_phys)); - // Translation table 1 is currently ignored - - // Clean the caches (data & instruction) - asm volatile("mcr p15, 0, %[r], c7, c14, 0" : : [r] "r" (0x0)); -} - -struct vas *vm_new_vas() -{ - if (!vm_vas_free_list) - { - return 0x0; - } - if (!vm_l1pt_free_list) - { - return 0x0; - } - struct vas *p = (struct vas*) vm_vas_free_list; - vm_vas_free_list = vm_vas_free_list->next; - - os_printf("vm_l1pt_free_list=%X\n", vm_l1pt_free_list); - p->l1_pagetable = (uint32_t*) vm_l1pt_free_list; - vm_l1pt_free_list = vm_l1pt_free_list->next; - - p->l1_pagetable_phys = (unsigned int*) ((unsigned int) p->l1_pagetable - - (V_L1PTBASE - P_L1PTBASE)); - - // Zero out the page table - os_memset(p->l1_pagetable, 0, PAGE_TABLE_SIZE); - - // Setup the static mappings... - // The kernel (high & low addresses) - //should be less than a MB - p->l1_pagetable[P_KERNBASE >> 20] = 0 << 20 | 0x0400 | 2; - - //also map it to high memory at 0xf0000000 - p->l1_pagetable[V_KERNBASE >> 20] = 0 << 20 | 0x0400 | 2; - p->l1_pagetable[(V_KERNBASE + 0x100000) >> 20] = 0x100000 | 0x0400 | 2; - - // Kernel datastructures - //temporarily map where it is until we copy it in VAS - p->l1_pagetable[P_KDSBASE >> 20] = P_KDSBASE | 0x0400 | 2; - - //1MB for static kernel data structures (stacks and l1 pt) - p->l1_pagetable[V_KDSBASE >> 20] = P_KDSBASE | 0x0400 | 2; - - // Our 1MB page to store VAS datastructures - p->l1_pagetable[V_L1PTBASE >> 20] = P_L1PTBASE | 0x0400 | 2; - - // 2MB of peripheral registers (so we get the serial port et. al.) - p->l1_pagetable[PERIPHBASE >> 20] = PERIPHBASE | 0x0400 | 2; - p->l1_pagetable[(PERIPHBASE + 0x100000) >> 20] = (PERIPHBASE + 0x100000) - | 0x0400 | 2; - return p; -} - -int vm_free_vas(struct vas *vas) -{ - struct vm_free_list *n = (struct vm_free_list*) vas->l1_pagetable; - n->next = vm_l1pt_free_list; - vm_l1pt_free_list = n; - - n = (struct vm_free_list*) vas; - n->next = vm_vas_free_list; - vm_vas_free_list = n; - return 0; -} diff --git a/qemu/build.sh b/qemu/build.sh index 481b0617..a4261a1b 100755 --- a/qemu/build.sh +++ b/qemu/build.sh @@ -1,17 +1,16 @@ #!/bin/bash -#QEMU_VERSION=1.6.2 -QEMU_VERSION=2.4.1 +QEMU_VERSION=4.2.0 -qemu-system-arm --version || { +{ + if [ ! -e qemu-${QEMU_VERSION}.tar.bz2 ]; then - if [ ! -e qemu-${QEMU_VERSION}.tar.bz2 ]; then wget http://wiki.qemu-project.org/download/qemu-${QEMU_VERSION}.tar.bz2 fi - if [ ! -d qemu-${QEMU_VERSION} ]; then + if [ ! -d qemu-${QEMU_VERSION} ]; then tar xvf qemu-${QEMU_VERSION}.tar.bz2 fi - cd qemu-${QEMU_VERSION}; ./configure --prefix=`pwd`/../qemu --target-list=arm-softmmu && make all install + cd qemu-${QEMU_VERSION} || exit 1; ./configure --prefix="$(pwd)/../qemu" --target-list=arm-softmmu && make all install } diff --git a/scripts/clang-format-all.sh b/scripts/clang-format-all.sh new file mode 100755 index 00000000..0ef6feac --- /dev/null +++ b/scripts/clang-format-all.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +shopt -s globstar + +DIR=$(dirname "$0")/.. + +eval clang-format -style=file $DIR/kernel/**/*.{c,h} -i + diff --git a/toolchain/build.sh b/toolchain/build.sh index 098c8478..092e072d 100755 --- a/toolchain/build.sh +++ b/toolchain/build.sh @@ -1,29 +1,29 @@ #!/bin/bash -PREFIX=`pwd`/arm-none-eabi -TARGET=`pwd`/target +PREFIX=$(pwd)/arm-none-eabi +TARGET=$(pwd)/target #TARGET=/tmp/course_os/target URL=ftp://ftp.gnu.org/gnu # toolchain -GCC_VERSION=4.8.1 -BINUTILS_VERSION=2.24 -NEWLIB_VERSION=2.0.0 -GDB_VERSION=7.7 +GCC_VERSION=9.2.0 +BINUTILS_VERSION=2.34 +NEWLIB_VERSION=3.1.0 +GDB_VERSION=9.1 GDB_EXT_VERSION=${GDB_VERSION} -if [ -e ${PREFIX} ]; then +if [ -e "${PREFIX}" ]; then exit 0; fi -rm -rf ${TARGET} +rm -rf "${TARGET}" -mkdir -p ${TARGET}/orig -mkdir -p ${TARGET}/src -mkdir -p ${TARGET}/build -mkdir -p ${TARGET}/buildroot +mkdir -p "${TARGET}/orig" +mkdir -p "${TARGET}/src" +mkdir -p "${TARGET}/build" +mkdir -p "${TARGET}/buildroot" -cd ${TARGET}/orig +cd "${TARGET}/orig" if [ ! -e gcc-${GCC_VERSION}.tar.gz ]; then wget ${URL}/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.gz || exit 1; @@ -41,33 +41,35 @@ if [ ! -e newlib-${NEWLIB_VERSION}.tar.gz ]; then wget ftp://sources.redhat.com/pub/newlib/newlib-${NEWLIB_VERSION}.tar.gz || exit 1; fi -cd ${TARGET}/src +cd "${TARGET}/src" + + +if [ ! -d "${TARGET}/src/gcc-${GCC_VERSION}" ]; then + tar xf ../orig/gcc-${GCC_VERSION}.tar.gz || exit 1; -if [ ! -d ${TARGET}/src/gcc-${GCC_VERSION} ]; then - tar xvf ../orig/gcc-${GCC_VERSION}.tar.gz || exit 1; fi -if [ ! -d ${TARGET}/src/gdb-${GDB_EXT_VERSION} ]; then - tar xvf ../orig/gdb-${GDB_EXT_VERSION}.tar.gz || exit 1; +if [ ! -d "${TARGET}/src/gdb-${GDB_EXT_VERSION}" ]; then + tar xf ../orig/gdb-${GDB_EXT_VERSION}.tar.gz || exit 1; fi -if [ ! -d ${TARGET}/src/binutils-${BINUTILS_VERSION} ]; then - tar xvf ../orig/binutils-${BINUTILS_VERSION}.tar.bz2 || exit 1; +if [ ! -d "${TARGET}/src/binutils-${BINUTILS_VERSION}" ]; then + tar xf ../orig/binutils-${BINUTILS_VERSION}.tar.bz2 || exit 1; fi -if [ ! -d ${TARGET}/src/newlib-${NEWLIB_VERSION} ]; then - tar xvf ../orig/newlib-${NEWLIB_VERSION}.tar.gz || exit 1; +if [ ! -d "${TARGET}/src/newlib-${NEWLIB_VERSION}" ]; then + tar xf ../orig/newlib-${NEWLIB_VERSION}.tar.gz || exit 1; fi -if [ ! -e ${PREFIX}/bin/arm-none-eabi-ld ]; then - mkdir -p ${TARGET}/build/binutils-${BINUTILS_VERSION} +if [ ! -e "${PREFIX}/bin/arm-none-eabi-ld" ]; then + mkdir -p "${TARGET}/build/binutils-${BINUTILS_VERSION}" sed -i -e 's/@colophon/@@colophon/g' \ - -e 's/doc@cygnus.com/doc@@cygnus.com/g' ${TARGET}/src/binutil s-${BINUTILS_VERSION}/bfd/doc/bfd.texinfo - cd ${TARGET}/build/binutils-${BINUTILS_VERSION} + -e 's/doc@cygnus.com/doc@@cygnus.com/g' "${TARGET}/src/binutils-${BINUTILS_VERSION}/bfd/doc/bfd.texinfo" + cd "${TARGET}/build/binutils-${BINUTILS_VERSION}" ../../src/binutils-${BINUTILS_VERSION}/configure \ --target=arm-none-eabi \ - --prefix=${PREFIX} \ + --prefix="${PREFIX}" \ --enable-interwork \ --enable-multilib \ --with-gnu-as \ @@ -78,14 +80,14 @@ if [ ! -e ${PREFIX}/bin/arm-none-eabi-ld ]; then fi export PATH="$PATH:${PREFIX}/bin" -mkdir -p ${TARGET}/build/gcc-${GCC_VERSION} -sed -i 's/BUILD_INFO=info/BUILD_INFO =/g' ${TARGET}/src/gcc-${GCC_VERSION}/gcc/configure -cd ${TARGET}/src/gcc-${GCC_VERSION} +mkdir -p "${TARGET}/build/gcc-${GCC_VERSION}" +sed -i 's/BUILD_INFO=info/BUILD_INFO =/g' "${TARGET}/src/gcc-${GCC_VERSION}/gcc/configure" +cd "${TARGET}/src/gcc-${GCC_VERSION}" ./contrib/download_prerequisites -cd ${TARGET}/build/gcc-${GCC_VERSION} +cd "${TARGET}/build/gcc-${GCC_VERSION}" ../../src/gcc-${GCC_VERSION}/configure \ --target=arm-none-eabi \ - --prefix=${PREFIX} \ + --prefix="${PREFIX}" \ --enable-interwork \ --enable-multilib \ --disable-nls \ @@ -96,11 +98,11 @@ cd ${TARGET}/build/gcc-${GCC_VERSION} --with-headers=../../src/newlib-${NEWLIB_VERSION}/newlib/libc/include || exit 1; make all-gcc && make install-gcc || exit 1; -mkdir -p ${TARGET}/build/newlib-${NEWLIB_VERSION} -cd ${TARGET}/build/newlib-${NEWLIB_VERSION} +mkdir -p "${TARGET}/build/newlib-${NEWLIB_VERSION}" +cd "${TARGET}/build/newlib-${NEWLIB_VERSION}" ../../src/newlib-${NEWLIB_VERSION}/configure \ --target=arm-none-eabi \ - --prefix=${PREFIX} \ + --prefix="${PREFIX}" \ --enable-interwork \ --with-gnu-as \ --with-gnu-ld \ @@ -112,12 +114,12 @@ cd ${TARGET}/build/newlib-${NEWLIB_VERSION} --enable-multilib || exit 1; make all && make install || exit 1; -cd ${TARGET}/build/gcc-${GCC_VERSION} +cd "${TARGET}/build/gcc-${GCC_VERSION}" make all install || exit 1; -mkdir -p ${TARGET}/build/gdb-${GDB_VERSION} -cd ${TARGET}/build/gdb-${GDB_VERSION} -../../src/gdb-${GDB_VERSION}/configure --target=arm-none-eabi --prefix=${PREFIX} --disable-werror --enable-interwork --enable-multilib || exit 1; +mkdir -p "${TARGET}/build/gdb-${GDB_VERSION}" +cd "${TARGET}/build/gdb-${GDB_VERSION}" +../../src/gdb-${GDB_VERSION}/configure --target=arm-none-eabi --prefix="${PREFIX}" --disable-werror --enable-interwork --enable-multilib || exit 1; make all && make install || exit 1; -rm -rf ${TARGET} +rm -rf "${TARGET}" diff --git a/u-boot/Makefile b/u-boot/Makefile deleted file mode 100644 index 31a47725..00000000 --- a/u-boot/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -include $(CURDIR)/../config.mk - -UBOOT_DIR:=u-boot-$(UBOOT_VERSION) -UBOOT_ARCHIVE:=$(UBOOT_DIR).tar.bz2 -UBOOT_URL:=ftp://ftp.denx.de/pub/u-boot/$(UBOOT_ARCHIVE) - -export PATH:=$(CURDIR)/../$(TOOLCHAIN_DIR)/$(BARE_METAL_TARGET)/bin:$(PATH) - -all: $(UBOOT_DIR)/u-boot.bin - -run: $(UBOOT_DIR)/u-boot.bin - ${QEMU} -M versatilepb -cpu arm1176 -m 128M -nographic -kernel $(UBOOT_DIR)/u-boot.bin - -$(UBOOT_DIR)/u-boot.bin: $(UBOOT_DIR) - -cd $(UBOOT_DIR); patch --silent --forward -p1 < ../versatile.patch - cd $(UBOOT_DIR); make versatileqemu_config ARCH=arm CPU=arm1136 CROSS_COMPILE=$(BARE_METAL_TUPLE)- - cp -r $(UBOOT_DIR)/arch/arm/cpu/arm926ejs/versatile $(UBOOT_DIR)/arch/arm/cpu/arm1136 - cd $(UBOOT_DIR); make all ARCH=arm CPU=arm1136 CROSS_COMPILE=$(BARE_METAL_TUPLE)- - -$(UBOOT_DIR): $(UBOOT_ARCHIVE) - tar xvf $(UBOOT_ARCHIVE) - -$(UBOOT_ARCHIVE): - wget $(UBOOT_URL) - -clean: - rm -rf $(UBOOT_DIR) - diff --git a/u-boot/versatile.patch b/u-boot/versatile.patch deleted file mode 100644 index 0acabcdf..00000000 --- a/u-boot/versatile.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- new/include/configs/versatile.h 2014-10-14 03:47:15.000000000 -0500 -+++ u-boot-2014.10/include/configs/versatile.h 2014-12-22 15:07:12.090798194 -0600 -@@ -100,9 +100,9 @@ - #define CONFIG_BOOTP_SUBNETMASK - - #define CONFIG_BOOTDELAY 2 --#define CONFIG_BOOTARGS "root=/dev/nfs mem=128M ip=dhcp "\ -- "netdev=25,0,0xf1010000,0xf1010010,eth0 "\ -- "console=ttyAMA0,38400n1" -+#define CONFIG_BOOTARGS "" -+#define CONFIG_CMD_SOURCE -+#define CONFIG_BOOTCOMMAND "source 24f000" - - /* - * Static configuration when assigning fixed address diff --git a/user/Makefile b/user/Makefile new file mode 100644 index 00000000..1b221f9d --- /dev/null +++ b/user/Makefile @@ -0,0 +1,17 @@ +include $(CURDIR)/../config.mk + +all: build + +CPU = cortex-a7 +CFLAGS += -pipe -std=gnu99 -ffreestanding -Wall -Werror -g -O0 -mcpu=arm1176jzf-s -march=armv6zk -mfpu=vfp -fpic -nostartfiles -nodefaultlibs +TOOLCHAIN_PATH:=$(CURDIR)/../$(TOOLCHAIN_DIR)/$(BARE_METAL_TARGET)/bin +CC:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-gcc +AS:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-as +LD:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-gcc +OBJCOPY:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-objcopy +GDB:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-gdb +CC:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-gcc + +build: + @$(CC) $(CFLAGS) -o ./swi/swi ./swi/swi.c +.PHONY: build diff --git a/user/gcc.specs b/user/gcc.specs deleted file mode 100644 index 0c8b4f2f..00000000 --- a/user/gcc.specs +++ /dev/null @@ -1,5 +0,0 @@ -*startfile: -../lib/crt1.o ../lib/crti.o - -*endfile: -../lib/crtn.o diff --git a/user/hello/Makefile b/user/hello/Makefile deleted file mode 100644 index 60a84733..00000000 --- a/user/hello/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -include $(CURDIR)/../../config.mk - -TOOLCHAIN_PATH:=$(CURDIR)/../../$(TOOLCHAIN_DIR)/$(BARE_METAL_TARGET)/bin -CC:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-gcc -LD:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-ld - -CFLAGS += -Os -pipe -CFLAGS += -std=c99 -ffreestanding -nostdinc - -PROGS = hello -PROGS += hello1 -PROGS += hello2 - -SPECS = -specs "../gcc.specs" - -all: $(PROGS) - -$(PROGS): %: %.o - $(CC) $(SPECS) -Wl,-Ttext-segment=0x9ff08000 -L../libc -static -lc $< -o $@ - -%.o: %.c - $(CC) $(SPECS) $(CFLAGS) -I../include -c $< -o $@ - -clean: - rm -f $(foreach prog,$(PROGS),$(prog).o) - rm -f $(PROGS) diff --git a/user/hello/hello.c b/user/hello/hello.c index 2026b289..f26b97c9 100644 --- a/user/hello/hello.c +++ b/user/hello/hello.c @@ -1,27 +1,6 @@ #include -#include "../libc/arch/arm/syscall_arch.h" -#include int main() { - __syscall3(99, 0, 0, 0); - - printf("Hello world... from hello.c\n"); - - printf("LET'S TEST %d\n", 10); - - int* mem = 0; - mem = (int*) malloc(100); - - printf("malloc returned %x\n", mem); - - mem[0] = 1; - mem[10] = 2; - - - - free(mem); - - printf("success\n"); - - while(1) { }; + printf("Hello, World!\n"); + return 0; } diff --git a/user/hello/hello1.c b/user/hello/hello1.c deleted file mode 100644 index 0d238195..00000000 --- a/user/hello/hello1.c +++ /dev/null @@ -1,9 +0,0 @@ -#include - -int main() { - while (1) - { - printf("Hello world... from hello1.c\n"); - for(int i=0; i<100000000; i++) { }; - } -} diff --git a/user/hello/hello2.c b/user/hello/hello2.c deleted file mode 100644 index 1b1c688e..00000000 --- a/user/hello/hello2.c +++ /dev/null @@ -1,9 +0,0 @@ -#include - -int main() { - while (1) - { - printf("Hello world... from hello2.c\n"); - for(int i=0; i<100000000; i++) { }; - } -} diff --git a/user/include/bits/alltypes.h b/user/include/bits/alltypes.h deleted file mode 100644 index 770cc5fe..00000000 --- a/user/include/bits/alltypes.h +++ /dev/null @@ -1,363 +0,0 @@ -#define _Addr int -#define _Int64 long long -#define _Reg int - -#if defined(__NEED_va_list) && !defined(__DEFINED_va_list) -typedef __builtin_va_list va_list; -#define __DEFINED_va_list -#endif - -#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list) -typedef __builtin_va_list __isoc_va_list; -#define __DEFINED___isoc_va_list -#endif - - -#ifndef __cplusplus -#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t) -typedef unsigned wchar_t; -#define __DEFINED_wchar_t -#endif - -#endif -#if defined(__NEED_wint_t) && !defined(__DEFINED_wint_t) -typedef unsigned wint_t; -#define __DEFINED_wint_t -#endif - - -#if defined(__NEED_float_t) && !defined(__DEFINED_float_t) -typedef float float_t; -#define __DEFINED_float_t -#endif - -#if defined(__NEED_double_t) && !defined(__DEFINED_double_t) -typedef double double_t; -#define __DEFINED_double_t -#endif - - -#if defined(__NEED_time_t) && !defined(__DEFINED_time_t) -typedef long time_t; -#define __DEFINED_time_t -#endif - -#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t) -typedef long suseconds_t; -#define __DEFINED_suseconds_t -#endif - - -#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t) -typedef struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; -#define __DEFINED_pthread_attr_t -#endif - -#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t) -typedef struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t; -#define __DEFINED_pthread_mutex_t -#endif - -#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t) -typedef struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; -#define __DEFINED_pthread_cond_t -#endif - -#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t) -typedef struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; -#define __DEFINED_pthread_rwlock_t -#endif - -#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t) -typedef struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; -#define __DEFINED_pthread_barrier_t -#endif - -#if defined(__NEED_size_t) && !defined(__DEFINED_size_t) -typedef unsigned _Addr size_t; -#define __DEFINED_size_t -#endif - -#if defined(__NEED_uintptr_t) && !defined(__DEFINED_uintptr_t) -typedef unsigned _Addr uintptr_t; -#define __DEFINED_uintptr_t -#endif - -#if defined(__NEED_ptrdiff_t) && !defined(__DEFINED_ptrdiff_t) -typedef _Addr ptrdiff_t; -#define __DEFINED_ptrdiff_t -#endif - -#if defined(__NEED_ssize_t) && !defined(__DEFINED_ssize_t) -typedef _Addr ssize_t; -#define __DEFINED_ssize_t -#endif - -#if defined(__NEED_intptr_t) && !defined(__DEFINED_intptr_t) -typedef _Addr intptr_t; -#define __DEFINED_intptr_t -#endif - -#if defined(__NEED_regoff_t) && !defined(__DEFINED_regoff_t) -typedef _Addr regoff_t; -#define __DEFINED_regoff_t -#endif - -#if defined(__NEED_register_t) && !defined(__DEFINED_register_t) -typedef _Reg register_t; -#define __DEFINED_register_t -#endif - - -#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t) -typedef signed char int8_t; -#define __DEFINED_int8_t -#endif - -#if defined(__NEED_int16_t) && !defined(__DEFINED_int16_t) -typedef short int16_t; -#define __DEFINED_int16_t -#endif - -#if defined(__NEED_int32_t) && !defined(__DEFINED_int32_t) -typedef int int32_t; -#define __DEFINED_int32_t -#endif - -#if defined(__NEED_int64_t) && !defined(__DEFINED_int64_t) -typedef _Int64 int64_t; -#define __DEFINED_int64_t -#endif - -#if defined(__NEED_intmax_t) && !defined(__DEFINED_intmax_t) -typedef _Int64 intmax_t; -#define __DEFINED_intmax_t -#endif - -#if defined(__NEED_uint8_t) && !defined(__DEFINED_uint8_t) -typedef unsigned char uint8_t; -#define __DEFINED_uint8_t -#endif - -#if defined(__NEED_uint16_t) && !defined(__DEFINED_uint16_t) -typedef unsigned short uint16_t; -#define __DEFINED_uint16_t -#endif - -#if defined(__NEED_uint32_t) && !defined(__DEFINED_uint32_t) -typedef unsigned int uint32_t; -#define __DEFINED_uint32_t -#endif - -#if defined(__NEED_uint64_t) && !defined(__DEFINED_uint64_t) -typedef unsigned _Int64 uint64_t; -#define __DEFINED_uint64_t -#endif - -#if defined(__NEED_u_int64_t) && !defined(__DEFINED_u_int64_t) -typedef unsigned _Int64 u_int64_t; -#define __DEFINED_u_int64_t -#endif - -#if defined(__NEED_uintmax_t) && !defined(__DEFINED_uintmax_t) -typedef unsigned _Int64 uintmax_t; -#define __DEFINED_uintmax_t -#endif - - -#if defined(__NEED_mode_t) && !defined(__DEFINED_mode_t) -typedef unsigned mode_t; -#define __DEFINED_mode_t -#endif - -#if defined(__NEED_nlink_t) && !defined(__DEFINED_nlink_t) -typedef unsigned _Reg nlink_t; -#define __DEFINED_nlink_t -#endif - -#if defined(__NEED_off_t) && !defined(__DEFINED_off_t) -typedef _Int64 off_t; -#define __DEFINED_off_t -#endif - -#if defined(__NEED_ino_t) && !defined(__DEFINED_ino_t) -typedef unsigned _Int64 ino_t; -#define __DEFINED_ino_t -#endif - -#if defined(__NEED_dev_t) && !defined(__DEFINED_dev_t) -typedef unsigned _Int64 dev_t; -#define __DEFINED_dev_t -#endif - -#if defined(__NEED_blksize_t) && !defined(__DEFINED_blksize_t) -typedef long blksize_t; -#define __DEFINED_blksize_t -#endif - -#if defined(__NEED_blkcnt_t) && !defined(__DEFINED_blkcnt_t) -typedef _Int64 blkcnt_t; -#define __DEFINED_blkcnt_t -#endif - -#if defined(__NEED_fsblkcnt_t) && !defined(__DEFINED_fsblkcnt_t) -typedef unsigned _Int64 fsblkcnt_t; -#define __DEFINED_fsblkcnt_t -#endif - -#if defined(__NEED_fsfilcnt_t) && !defined(__DEFINED_fsfilcnt_t) -typedef unsigned _Int64 fsfilcnt_t; -#define __DEFINED_fsfilcnt_t -#endif - - -#if defined(__NEED_wctype_t) && !defined(__DEFINED_wctype_t) -typedef unsigned long wctype_t; -#define __DEFINED_wctype_t -#endif - - -#if defined(__NEED_timer_t) && !defined(__DEFINED_timer_t) -typedef void * timer_t; -#define __DEFINED_timer_t -#endif - -#if defined(__NEED_clockid_t) && !defined(__DEFINED_clockid_t) -typedef int clockid_t; -#define __DEFINED_clockid_t -#endif - -#if defined(__NEED_clock_t) && !defined(__DEFINED_clock_t) -typedef long clock_t; -#define __DEFINED_clock_t -#endif - -#if defined(__NEED_struct_timeval) && !defined(__DEFINED_struct_timeval) -struct timeval { time_t tv_sec; suseconds_t tv_usec; }; -#define __DEFINED_struct_timeval -#endif - -#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec) -struct timespec { time_t tv_sec; long tv_nsec; }; -#define __DEFINED_struct_timespec -#endif - - -#if defined(__NEED_pid_t) && !defined(__DEFINED_pid_t) -typedef int pid_t; -#define __DEFINED_pid_t -#endif - -#if defined(__NEED_id_t) && !defined(__DEFINED_id_t) -typedef unsigned id_t; -#define __DEFINED_id_t -#endif - -#if defined(__NEED_uid_t) && !defined(__DEFINED_uid_t) -typedef unsigned uid_t; -#define __DEFINED_uid_t -#endif - -#if defined(__NEED_gid_t) && !defined(__DEFINED_gid_t) -typedef unsigned gid_t; -#define __DEFINED_gid_t -#endif - -#if defined(__NEED_key_t) && !defined(__DEFINED_key_t) -typedef int key_t; -#define __DEFINED_key_t -#endif - -#if defined(__NEED_useconds_t) && !defined(__DEFINED_useconds_t) -typedef unsigned useconds_t; -#define __DEFINED_useconds_t -#endif - - -#ifdef __cplusplus -#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t) -typedef unsigned long pthread_t; -#define __DEFINED_pthread_t -#endif - -#else -#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t) -typedef struct __pthread * pthread_t; -#define __DEFINED_pthread_t -#endif - -#endif -#if defined(__NEED_pthread_once_t) && !defined(__DEFINED_pthread_once_t) -typedef int pthread_once_t; -#define __DEFINED_pthread_once_t -#endif - -#if defined(__NEED_pthread_key_t) && !defined(__DEFINED_pthread_key_t) -typedef unsigned pthread_key_t; -#define __DEFINED_pthread_key_t -#endif - -#if defined(__NEED_pthread_spinlock_t) && !defined(__DEFINED_pthread_spinlock_t) -typedef int pthread_spinlock_t; -#define __DEFINED_pthread_spinlock_t -#endif - -#if defined(__NEED_pthread_mutexattr_t) && !defined(__DEFINED_pthread_mutexattr_t) -typedef struct { unsigned __attr; } pthread_mutexattr_t; -#define __DEFINED_pthread_mutexattr_t -#endif - -#if defined(__NEED_pthread_condattr_t) && !defined(__DEFINED_pthread_condattr_t) -typedef struct { unsigned __attr; } pthread_condattr_t; -#define __DEFINED_pthread_condattr_t -#endif - -#if defined(__NEED_pthread_barrierattr_t) && !defined(__DEFINED_pthread_barrierattr_t) -typedef struct { unsigned __attr; } pthread_barrierattr_t; -#define __DEFINED_pthread_barrierattr_t -#endif - -#if defined(__NEED_pthread_rwlockattr_t) && !defined(__DEFINED_pthread_rwlockattr_t) -typedef struct { unsigned __attr[2]; } pthread_rwlockattr_t; -#define __DEFINED_pthread_rwlockattr_t -#endif - - -#if defined(__NEED_FILE) && !defined(__DEFINED_FILE) -typedef struct _IO_FILE FILE; -#define __DEFINED_FILE -#endif - - -#if defined(__NEED_locale_t) && !defined(__DEFINED_locale_t) -typedef struct __locale_struct * locale_t; -#define __DEFINED_locale_t -#endif - - -#if defined(__NEED_sigset_t) && !defined(__DEFINED_sigset_t) -typedef struct __sigset_t { unsigned long __bits[128/sizeof(long)]; } sigset_t; -#define __DEFINED_sigset_t -#endif - - -#if defined(__NEED_struct_iovec) && !defined(__DEFINED_struct_iovec) -struct iovec { void *iov_base; size_t iov_len; }; -#define __DEFINED_struct_iovec -#endif - - -#if defined(__NEED_socklen_t) && !defined(__DEFINED_socklen_t) -typedef unsigned socklen_t; -#define __DEFINED_socklen_t -#endif - -#if defined(__NEED_sa_family_t) && !defined(__DEFINED_sa_family_t) -typedef unsigned short sa_family_t; -#define __DEFINED_sa_family_t -#endif - - -#undef _Addr -#undef _Int64 -#undef _Reg diff --git a/user/include/bits/errno.h b/user/include/bits/errno.h deleted file mode 100644 index d2e1eeee..00000000 --- a/user/include/bits/errno.h +++ /dev/null @@ -1,134 +0,0 @@ -#define EPERM 1 -#define ENOENT 2 -#define ESRCH 3 -#define EINTR 4 -#define EIO 5 -#define ENXIO 6 -#define E2BIG 7 -#define ENOEXEC 8 -#define EBADF 9 -#define ECHILD 10 -#define EAGAIN 11 -#define ENOMEM 12 -#define EACCES 13 -#define EFAULT 14 -#define ENOTBLK 15 -#define EBUSY 16 -#define EEXIST 17 -#define EXDEV 18 -#define ENODEV 19 -#define ENOTDIR 20 -#define EISDIR 21 -#define EINVAL 22 -#define ENFILE 23 -#define EMFILE 24 -#define ENOTTY 25 -#define ETXTBSY 26 -#define EFBIG 27 -#define ENOSPC 28 -#define ESPIPE 29 -#define EROFS 30 -#define EMLINK 31 -#define EPIPE 32 -#define EDOM 33 -#define ERANGE 34 -#define EDEADLK 35 -#define ENAMETOOLONG 36 -#define ENOLCK 37 -#define ENOSYS 38 -#define ENOTEMPTY 39 -#define ELOOP 40 -#define EWOULDBLOCK EAGAIN -#define ENOMSG 42 -#define EIDRM 43 -#define ECHRNG 44 -#define EL2NSYNC 45 -#define EL3HLT 46 -#define EL3RST 47 -#define ELNRNG 48 -#define EUNATCH 49 -#define ENOCSI 50 -#define EL2HLT 51 -#define EBADE 52 -#define EBADR 53 -#define EXFULL 54 -#define ENOANO 55 -#define EBADRQC 56 -#define EBADSLT 57 -#define EDEADLOCK EDEADLK -#define EBFONT 59 -#define ENOSTR 60 -#define ENODATA 61 -#define ETIME 62 -#define ENOSR 63 -#define ENONET 64 -#define ENOPKG 65 -#define EREMOTE 66 -#define ENOLINK 67 -#define EADV 68 -#define ESRMNT 69 -#define ECOMM 70 -#define EPROTO 71 -#define EMULTIHOP 72 -#define EDOTDOT 73 -#define EBADMSG 74 -#define EOVERFLOW 75 -#define ENOTUNIQ 76 -#define EBADFD 77 -#define EREMCHG 78 -#define ELIBACC 79 -#define ELIBBAD 80 -#define ELIBSCN 81 -#define ELIBMAX 82 -#define ELIBEXEC 83 -#define EILSEQ 84 -#define ERESTART 85 -#define ESTRPIPE 86 -#define EUSERS 87 -#define ENOTSOCK 88 -#define EDESTADDRREQ 89 -#define EMSGSIZE 90 -#define EPROTOTYPE 91 -#define ENOPROTOOPT 92 -#define EPROTONOSUPPORT 93 -#define ESOCKTNOSUPPORT 94 -#define EOPNOTSUPP 95 -#define ENOTSUP EOPNOTSUPP -#define EPFNOSUPPORT 96 -#define EAFNOSUPPORT 97 -#define EADDRINUSE 98 -#define EADDRNOTAVAIL 99 -#define ENETDOWN 100 -#define ENETUNREACH 101 -#define ENETRESET 102 -#define ECONNABORTED 103 -#define ECONNRESET 104 -#define ENOBUFS 105 -#define EISCONN 106 -#define ENOTCONN 107 -#define ESHUTDOWN 108 -#define ETOOMANYREFS 109 -#define ETIMEDOUT 110 -#define ECONNREFUSED 111 -#define EHOSTDOWN 112 -#define EHOSTUNREACH 113 -#define EALREADY 114 -#define EINPROGRESS 115 -#define ESTALE 116 -#define EUCLEAN 117 -#define ENOTNAM 118 -#define ENAVAIL 119 -#define EISNAM 120 -#define EREMOTEIO 121 -#define EDQUOT 122 -#define ENOMEDIUM 123 -#define EMEDIUMTYPE 124 -#define ECANCELED 125 -#define ENOKEY 126 -#define EKEYEXPIRED 127 -#define EKEYREVOKED 128 -#define EKEYREJECTED 129 -#define EOWNERDEAD 130 -#define ENOTRECOVERABLE 131 -#define ERFKILL 132 -#define EHWPOISON 133 diff --git a/user/include/bits/float.h b/user/include/bits/float.h deleted file mode 100644 index ec46b94b..00000000 --- a/user/include/bits/float.h +++ /dev/null @@ -1,17 +0,0 @@ -#define FLT_ROUNDS 1 -#define FLT_EVAL_METHOD 0 - -#define LDBL_TRUE_MIN 4.94065645841246544177e-324L -#define LDBL_MIN 2.22507385850720138309e-308L -#define LDBL_MAX 1.79769313486231570815e+308L -#define LDBL_EPSILON 2.22044604925031308085e-16L - -#define LDBL_MANT_DIG 53 -#define LDBL_MIN_EXP (-1021) -#define LDBL_MAX_EXP 1024 - -#define LDBL_DIG 15 -#define LDBL_MIN_10_EXP (-307) -#define LDBL_MAX_10_EXP 308 - -#define DECIMAL_DIG 17 diff --git a/user/include/bits/ioctl.h b/user/include/bits/ioctl.h deleted file mode 100644 index 9d75118e..00000000 --- a/user/include/bits/ioctl.h +++ /dev/null @@ -1,197 +0,0 @@ -#define _IOC(a,b,c,d) ( ((a)<<30) | ((b)<<8) | (c) | ((d)<<16) ) -#define _IOC_NONE 0U -#define _IOC_WRITE 1U -#define _IOC_READ 2U - -#define _IO(a,b) _IOC(_IOC_NONE,(a),(b),0) -#define _IOW(a,b,c) _IOC(_IOC_WRITE,(a),(b),sizeof(c)) -#define _IOR(a,b,c) _IOC(_IOC_READ,(a),(b),sizeof(c)) -#define _IOWR(a,b,c) _IOC(_IOC_READ|_IOC_WRITE,(a),(b),sizeof(c)) - -#define TCGETS 0x5401 -#define TCSETS 0x5402 -#define TCSETSW 0x5403 -#define TCSETSF 0x5404 -#define TCGETA 0x5405 -#define TCSETA 0x5406 -#define TCSETAW 0x5407 -#define TCSETAF 0x5408 -#define TCSBRK 0x5409 -#define TCXONC 0x540A -#define TCFLSH 0x540B -#define TIOCEXCL 0x540C -#define TIOCNXCL 0x540D -#define TIOCSCTTY 0x540E -#define TIOCGPGRP 0x540F -#define TIOCSPGRP 0x5410 -#define TIOCOUTQ 0x5411 -#define TIOCSTI 0x5412 -#define TIOCGWINSZ 0x5413 -#define TIOCSWINSZ 0x5414 -#define TIOCMGET 0x5415 -#define TIOCMBIS 0x5416 -#define TIOCMBIC 0x5417 -#define TIOCMSET 0x5418 -#define TIOCGSOFTCAR 0x5419 -#define TIOCSSOFTCAR 0x541A -#define FIONREAD 0x541B -#define TIOCINQ FIONREAD -#define TIOCLINUX 0x541C -#define TIOCCONS 0x541D -#define TIOCGSERIAL 0x541E -#define TIOCSSERIAL 0x541F -#define TIOCPKT 0x5420 -#define FIONBIO 0x5421 -#define TIOCNOTTY 0x5422 -#define TIOCSETD 0x5423 -#define TIOCGETD 0x5424 -#define TCSBRKP 0x5425 -#define TIOCTTYGSTRUCT 0x5426 -#define TIOCSBRK 0x5427 -#define TIOCCBRK 0x5428 -#define TIOCGSID 0x5429 -#define TIOCGPTN 0x80045430 -#define TIOCSPTLCK 0x40045431 -#define TCGETX 0x5432 -#define TCSETX 0x5433 -#define TCSETXF 0x5434 -#define TCSETXW 0x5435 - -#define FIONCLEX 0x5450 -#define FIOCLEX 0x5451 -#define FIOASYNC 0x5452 -#define TIOCSERCONFIG 0x5453 -#define TIOCSERGWILD 0x5454 -#define TIOCSERSWILD 0x5455 -#define TIOCGLCKTRMIOS 0x5456 -#define TIOCSLCKTRMIOS 0x5457 -#define TIOCSERGSTRUCT 0x5458 -#define TIOCSERGETLSR 0x5459 -#define TIOCSERGETMULTI 0x545A -#define TIOCSERSETMULTI 0x545B - -#define TIOCMIWAIT 0x545C -#define TIOCGICOUNT 0x545D -#define TIOCGHAYESESP 0x545E -#define TIOCSHAYESESP 0x545F -#define FIOQSIZE 0x5460 - -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 -#define TIOCPKT_IOCTL 64 - -#define TIOCSER_TEMT 0x01 - -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG -#define TIOCM_OUT1 0x2000 -#define TIOCM_OUT2 0x4000 -#define TIOCM_LOOP 0x8000 -#define TIOCM_MODEM_BITS TIOCM_OUT2 - -#define N_TTY 0 -#define N_SLIP 1 -#define N_MOUSE 2 -#define N_PPP 3 -#define N_STRIP 4 -#define N_AX25 5 -#define N_X25 6 -#define N_6PACK 7 -#define N_MASC 8 -#define N_R3964 9 -#define N_PROFIBUS_FDL 10 -#define N_IRDA 11 -#define N_SMSBLOCK 12 -#define N_HDLC 13 -#define N_SYNC_PPP 14 -#define N_HCI 15 - -#define FIOSETOWN 0x8901 -#define SIOCSPGRP 0x8902 -#define FIOGETOWN 0x8903 -#define SIOCGPGRP 0x8904 -#define SIOCATMARK 0x8905 -#define SIOCGSTAMP 0x8906 - -#define SIOCADDRT 0x890B -#define SIOCDELRT 0x890C -#define SIOCRTMSG 0x890D - -#define SIOCGIFNAME 0x8910 -#define SIOCSIFLINK 0x8911 -#define SIOCGIFCONF 0x8912 -#define SIOCGIFFLAGS 0x8913 -#define SIOCSIFFLAGS 0x8914 -#define SIOCGIFADDR 0x8915 -#define SIOCSIFADDR 0x8916 -#define SIOCGIFDSTADDR 0x8917 -#define SIOCSIFDSTADDR 0x8918 -#define SIOCGIFBRDADDR 0x8919 -#define SIOCSIFBRDADDR 0x891a -#define SIOCGIFNETMASK 0x891b -#define SIOCSIFNETMASK 0x891c -#define SIOCGIFMETRIC 0x891d -#define SIOCSIFMETRIC 0x891e -#define SIOCGIFMEM 0x891f -#define SIOCSIFMEM 0x8920 -#define SIOCGIFMTU 0x8921 -#define SIOCSIFMTU 0x8922 -#define SIOCSIFHWADDR 0x8924 -#define SIOCGIFENCAP 0x8925 -#define SIOCSIFENCAP 0x8926 -#define SIOCGIFHWADDR 0x8927 -#define SIOCGIFSLAVE 0x8929 -#define SIOCSIFSLAVE 0x8930 -#define SIOCADDMULTI 0x8931 -#define SIOCDELMULTI 0x8932 -#define SIOCGIFINDEX 0x8933 -#define SIOGIFINDEX SIOCGIFINDEX -#define SIOCSIFPFLAGS 0x8934 -#define SIOCGIFPFLAGS 0x8935 -#define SIOCDIFADDR 0x8936 -#define SIOCSIFHWBROADCAST 0x8937 -#define SIOCGIFCOUNT 0x8938 - -#define SIOCGIFBR 0x8940 -#define SIOCSIFBR 0x8941 - -#define SIOCGIFTXQLEN 0x8942 -#define SIOCSIFTXQLEN 0x8943 - -#define SIOCDARP 0x8953 -#define SIOCGARP 0x8954 -#define SIOCSARP 0x8955 - -#define SIOCDRARP 0x8960 -#define SIOCGRARP 0x8961 -#define SIOCSRARP 0x8962 - -#define SIOCGIFMAP 0x8970 -#define SIOCSIFMAP 0x8971 - -#define SIOCADDDLCI 0x8980 -#define SIOCDELDLCI 0x8981 - -#define SIOCDEVPRIVATE 0x89F0 -#define SIOCPROTOPRIVATE 0x89E0 diff --git a/user/include/bits/limits.h b/user/include/bits/limits.h deleted file mode 100644 index 65a3dd64..00000000 --- a/user/include/bits/limits.h +++ /dev/null @@ -1,8 +0,0 @@ -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define PAGE_SIZE 4096 -#define LONG_BIT 32 -#endif - -#define LONG_MAX 0x7fffffffL -#define LLONG_MAX 0x7fffffffffffffffLL diff --git a/user/include/bits/stdint.h b/user/include/bits/stdint.h deleted file mode 100644 index d1b27121..00000000 --- a/user/include/bits/stdint.h +++ /dev/null @@ -1,20 +0,0 @@ -typedef int32_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef uint32_t uint_fast16_t; -typedef uint32_t uint_fast32_t; - -#define INT_FAST16_MIN INT32_MIN -#define INT_FAST32_MIN INT32_MIN - -#define INT_FAST16_MAX INT32_MAX -#define INT_FAST32_MAX INT32_MAX - -#define UINT_FAST16_MAX UINT32_MAX -#define UINT_FAST32_MAX UINT32_MAX - -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX -#define PTRDIFF_MIN INT32_MIN -#define PTRDIFF_MAX INT32_MAX -#define SIZE_MAX UINT32_MAX diff --git a/user/include/bits/syscall.h b/user/include/bits/syscall.h deleted file mode 100644 index dc54bdef..00000000 --- a/user/include/bits/syscall.h +++ /dev/null @@ -1,674 +0,0 @@ -#define __NR_restart_syscall 0 -#define __NR_exit 1 -#define __NR_fork 2 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_creat 8 -#define __NR_link 9 -#define __NR_unlink 10 -#define __NR_execve 11 -#define __NR_chdir 12 -#define __NR_mknod 14 -#define __NR_chmod 15 -#define __NR_lchown 16 -#define __NR_lseek 19 -#define __NR_getpid 20 -#define __NR_mount 21 -#define __NR_setuid 23 -#define __NR_getuid 24 -#define __NR_ptrace 26 -#define __NR_pause 29 -#define __NR_access 33 -#define __NR_nice 34 -#define __NR_sync 36 -#define __NR_kill 37 -#define __NR_rename 38 -#define __NR_mkdir 39 -#define __NR_rmdir 40 -#define __NR_dup 41 -#define __NR_pipe 42 -#define __NR_times 43 -#define __NR_brk 45 -#define __NR_setgid 46 -#define __NR_getgid 47 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_acct 51 -#define __NR_umount2 52 -#define __NR_ioctl 54 -#define __NR_fcntl 55 -#define __NR_setpgid 57 -#define __NR_umask 60 -#define __NR_chroot 61 -#define __NR_ustat 62 -#define __NR_dup2 63 -#define __NR_getppid 64 -#define __NR_getpgrp 65 -#define __NR_setsid 66 -#define __NR_sigaction 67 -#define __NR_setreuid 70 -#define __NR_setregid 71 -#define __NR_sigsuspend 72 -#define __NR_sigpending 73 -#define __NR_sethostname 74 -#define __NR_setrlimit 75 -#define __NR_getrusage 77 -#define __NR_gettimeofday 78 -#define __NR_settimeofday 79 -#define __NR_getgroups 80 -#define __NR_setgroups 81 -#define __NR_symlink 83 -#define __NR_readlink 85 -#define __NR_uselib 86 -#define __NR_swapon 87 -#define __NR_reboot 88 -#define __NR_munmap 91 -#define __NR_truncate 92 -#define __NR_ftruncate 93 -#define __NR_fchmod 94 -#define __NR_fchown 95 -#define __NR_getpriority 96 -#define __NR_setpriority 97 -#define __NR_statfs 99 -#define __NR_fstatfs 100 -#define __NR_syslog 103 -#define __NR_setitimer 104 -#define __NR_getitimer 105 -#define __NR_stat 106 -#define __NR_lstat 107 -#define __NR_fstat 108 -#define __NR_vhangup 111 -#define __NR_wait4 114 -#define __NR_swapoff 115 -#define __NR_sysinfo 116 -#define __NR_fsync 118 -#define __NR_sigreturn 119 -#define __NR_clone 120 -#define __NR_setdomainname 121 -#define __NR_uname 122 -#define __NR_adjtimex 124 -#define __NR_mprotect 125 -#define __NR_sigprocmask 126 -#define __NR_init_module 128 -#define __NR_delete_module 129 -#define __NR_quotactl 131 -#define __NR_getpgid 132 -#define __NR_fchdir 133 -#define __NR_bdflush 134 -#define __NR_sysfs 135 -#define __NR_personality 136 -#define __NR_setfsuid 138 -#define __NR_setfsgid 139 -#define __NR__llseek 140 -#define __NR_getdents 141 -#define __NR__newselect 142 -#define __NR_flock 143 -#define __NR_msync 144 -#define __NR_readv 145 -#define __NR_writev 146 -#define __NR_getsid 147 -#define __NR_fdatasync 148 -#define __NR__sysctl 149 -#define __NR_mlock 150 -#define __NR_munlock 151 -#define __NR_mlockall 152 -#define __NR_munlockall 153 -#define __NR_sched_setparam 154 -#define __NR_sched_getparam 155 -#define __NR_sched_setscheduler 156 -#define __NR_sched_getscheduler 157 -#define __NR_sched_yield 158 -#define __NR_sched_get_priority_max 159 -#define __NR_sched_get_priority_min 160 -#define __NR_sched_rr_get_interval 161 -#define __NR_nanosleep 162 -#define __NR_mremap 163 -#define __NR_setresuid 164 -#define __NR_getresuid 165 -#define __NR_poll 168 -#define __NR_nfsservctl 169 -#define __NR_setresgid 170 -#define __NR_getresgid 171 -#define __NR_prctl 172 -#define __NR_rt_sigreturn 173 -#define __NR_rt_sigaction 174 -#define __NR_rt_sigprocmask 175 -#define __NR_rt_sigpending 176 -#define __NR_rt_sigtimedwait 177 -#define __NR_rt_sigqueueinfo 178 -#define __NR_rt_sigsuspend 179 -#define __NR_pread64 180 -#define __NR_pwrite64 181 -#define __NR_chown 182 -#define __NR_getcwd 183 -#define __NR_capget 184 -#define __NR_capset 185 -#define __NR_sigaltstack 186 -#define __NR_sendfile 187 -#define __NR_vfork 190 -#define __NR_ugetrlimit 191 -#define __NR_mmap2 192 -#define __NR_truncate64 193 -#define __NR_ftruncate64 194 -#define __NR_stat64 195 -#define __NR_lstat64 196 -#define __NR_fstat64 197 -#define __NR_lchown32 198 -#define __NR_getuid32 199 -#define __NR_getgid32 200 -#define __NR_geteuid32 201 -#define __NR_getegid32 202 -#define __NR_setreuid32 203 -#define __NR_setregid32 204 -#define __NR_getgroups32 205 -#define __NR_setgroups32 206 -#define __NR_fchown32 207 -#define __NR_setresuid32 208 -#define __NR_getresuid32 209 -#define __NR_setresgid32 210 -#define __NR_getresgid32 211 -#define __NR_chown32 212 -#define __NR_setuid32 213 -#define __NR_setgid32 214 -#define __NR_setfsuid32 215 -#define __NR_setfsgid32 216 -#define __NR_getdents64 217 -#define __NR_pivot_root 218 -#define __NR_mincore 219 -#define __NR_madvise 220 -#define __NR_fcntl64 221 -#define __NR_gettid 224 -#define __NR_readahead 225 -#define __NR_setxattr 226 -#define __NR_lsetxattr 227 -#define __NR_fsetxattr 228 -#define __NR_getxattr 229 -#define __NR_lgetxattr 230 -#define __NR_fgetxattr 231 -#define __NR_listxattr 232 -#define __NR_llistxattr 233 -#define __NR_flistxattr 234 -#define __NR_removexattr 235 -#define __NR_lremovexattr 236 -#define __NR_fremovexattr 237 -#define __NR_tkill 238 -#define __NR_sendfile64 239 -#define __NR_futex 240 -#define __NR_sched_setaffinity 241 -#define __NR_sched_getaffinity 242 -#define __NR_io_setup 243 -#define __NR_io_destroy 244 -#define __NR_io_getevents 245 -#define __NR_io_submit 246 -#define __NR_io_cancel 247 -#define __NR_exit_group 248 -#define __NR_lookup_dcookie 249 -#define __NR_epoll_create 250 -#define __NR_epoll_ctl 251 -#define __NR_epoll_wait 252 -#define __NR_remap_file_pages 253 -#define __NR_set_tid_address 256 -#define __NR_timer_create 257 -#define __NR_timer_settime 258 -#define __NR_timer_gettime 259 -#define __NR_timer_getoverrun 260 -#define __NR_timer_delete 261 -#define __NR_clock_settime 262 -#define __NR_clock_gettime 263 -#define __NR_clock_getres 264 -#define __NR_clock_nanosleep 265 -#define __NR_statfs64 266 -#define __NR_fstatfs64 267 -#define __NR_tgkill 268 -#define __NR_utimes 269 -#define __NR_fadvise64_64 270 -#define __NR_pciconfig_iobase 271 -#define __NR_pciconfig_read 272 -#define __NR_pciconfig_write 273 -#define __NR_mq_open 274 -#define __NR_mq_unlink 275 -#define __NR_mq_timedsend 276 -#define __NR_mq_timedreceive 277 -#define __NR_mq_notify 278 -#define __NR_mq_getsetattr 279 -#define __NR_waitid 280 -#define __NR_socket 281 -#define __NR_bind 282 -#define __NR_connect 283 -#define __NR_listen 284 -#define __NR_accept 285 -#define __NR_getsockname 286 -#define __NR_getpeername 287 -#define __NR_socketpair 288 -#define __NR_send 289 -#define __NR_sendto 290 -#define __NR_recv 291 -#define __NR_recvfrom 292 -#define __NR_shutdown 293 -#define __NR_setsockopt 294 -#define __NR_getsockopt 295 -#define __NR_sendmsg 296 -#define __NR_recvmsg 297 -#define __NR_semop 298 -#define __NR_semget 299 -#define __NR_semctl 300 -#define __NR_msgsnd 301 -#define __NR_msgrcv 302 -#define __NR_msgget 303 -#define __NR_msgctl 304 -#define __NR_shmat 305 -#define __NR_shmdt 306 -#define __NR_shmget 307 -#define __NR_shmctl 308 -#define __NR_add_key 309 -#define __NR_request_key 310 -#define __NR_keyctl 311 -#define __NR_semtimedop 312 -#define __NR_vserver 313 -#define __NR_ioprio_set 314 -#define __NR_ioprio_get 315 -#define __NR_inotify_init 316 -#define __NR_inotify_add_watch 317 -#define __NR_inotify_rm_watch 318 -#define __NR_mbind 319 -#define __NR_get_mempolicy 320 -#define __NR_set_mempolicy 321 -#define __NR_openat 322 -#define __NR_mkdirat 323 -#define __NR_mknodat 324 -#define __NR_fchownat 325 -#define __NR_futimesat 326 -#define __NR_fstatat64 327 -#define __NR_unlinkat 328 -#define __NR_renameat 329 -#define __NR_linkat 330 -#define __NR_symlinkat 331 -#define __NR_readlinkat 332 -#define __NR_fchmodat 333 -#define __NR_faccessat 334 -#define __NR_pselect6 335 -#define __NR_ppoll 336 -#define __NR_unshare 337 -#define __NR_set_robust_list 338 -#define __NR_get_robust_list 339 -#define __NR_splice 340 -#define __NR_sync_file_range2 341 -#define __NR_tee 342 -#define __NR_vmsplice 343 -#define __NR_move_pages 344 -#define __NR_getcpu 345 -#define __NR_epoll_pwait 346 -#define __NR_kexec_load 347 -#define __NR_utimensat 348 -#define __NR_signalfd 349 -#define __NR_timerfd_create 350 -#define __NR_eventfd 351 -#define __NR_fallocate 352 -#define __NR_timerfd_settime 353 -#define __NR_timerfd_gettime 354 -#define __NR_signalfd4 355 -#define __NR_eventfd2 356 -#define __NR_epoll_create1 357 -#define __NR_dup3 358 -#define __NR_pipe2 359 -#define __NR_inotify_init1 360 -#define __NR_preadv 361 -#define __NR_pwritev 362 -#define __NR_rt_tgsigqueueinfo 363 -#define __NR_perf_event_open 364 -#define __NR_recvmmsg 365 -#define __NR_accept4 366 -#define __NR_fanotify_init 367 -#define __NR_fanotify_mark 368 -#define __NR_prlimit64 369 -#define __NR_name_to_handle_at 370 -#define __NR_open_by_handle_at 371 -#define __NR_clock_adjtime 372 -#define __NR_syncfs 373 -#define __NR_sendmmsg 374 -#define __NR_setns 375 -#define __NR_process_vm_readv 376 -#define __NR_process_vm_writev 377 -#define __NR_kcmp 378 -#define __NR_finit_module 379 - - -/* Repeated with SYS_ prefix */ - -#define SYS_restart_syscall 0 -#define SYS_exit 1 -#define SYS_fork 2 -#define SYS_read 3 -#define SYS_write 4 -#define SYS_open 5 -#define SYS_close 6 -#define SYS_creat 8 -#define SYS_link 9 -#define SYS_unlink 10 -#define SYS_execve 11 -#define SYS_chdir 12 -#define SYS_mknod 14 -#define SYS_chmod 15 -#define SYS_lchown 16 -#define SYS_lseek 19 -#define SYS_getpid 20 -#define SYS_mount 21 -#define SYS_setuid 23 -#define SYS_getuid 24 -#define SYS_ptrace 26 -#define SYS_pause 29 -#define SYS_access 33 -#define SYS_nice 34 -#define SYS_sync 36 -#define SYS_kill 37 -#define SYS_rename 38 -#define SYS_mkdir 39 -#define SYS_rmdir 40 -#define SYS_dup 41 -#define SYS_pipe 42 -#define SYS_times 43 -#define SYS_brk 45 -#define SYS_setgid 46 -#define SYS_getgid 47 -#define SYS_geteuid 49 -#define SYS_getegid 50 -#define SYS_acct 51 -#define SYS_umount2 52 -#define SYS_ioctl 54 -#define SYS_fcntl 55 -#define SYS_setpgid 57 -#define SYS_umask 60 -#define SYS_chroot 61 -#define SYS_ustat 62 -#define SYS_dup2 63 -#define SYS_getppid 64 -#define SYS_getpgrp 65 -#define SYS_setsid 66 -#define SYS_sigaction 67 -#define SYS_setreuid 70 -#define SYS_setregid 71 -#define SYS_sigsuspend 72 -#define SYS_sigpending 73 -#define SYS_sethostname 74 -#define SYS_setrlimit 75 -#define SYS_getrusage 77 -#define SYS_gettimeofday 78 -#define SYS_settimeofday 79 -#define SYS_getgroups 80 -#define SYS_setgroups 81 -#define SYS_symlink 83 -#define SYS_readlink 85 -#define SYS_uselib 86 -#define SYS_swapon 87 -#define SYS_reboot 88 -#define SYS_munmap 91 -#define SYS_truncate 92 -#define SYS_ftruncate 93 -#define SYS_fchmod 94 -#define SYS_fchown 95 -#define SYS_getpriority 96 -#define SYS_setpriority 97 -#define SYS_statfs 99 -#define SYS_fstatfs 100 -#define SYS_syslog 103 -#define SYS_setitimer 104 -#define SYS_getitimer 105 -#define SYS_stat 106 -#define SYS_lstat 107 -#define SYS_fstat 108 -#define SYS_vhangup 111 -#define SYS_wait4 114 -#define SYS_swapoff 115 -#define SYS_sysinfo 116 -#define SYS_fsync 118 -#define SYS_sigreturn 119 -#define SYS_clone 120 -#define SYS_setdomainname 121 -#define SYS_uname 122 -#define SYS_adjtimex 124 -#define SYS_mprotect 125 -#define SYS_sigprocmask 126 -#define SYS_init_module 128 -#define SYS_delete_module 129 -#define SYS_quotactl 131 -#define SYS_getpgid 132 -#define SYS_fchdir 133 -#define SYS_bdflush 134 -#define SYS_sysfs 135 -#define SYS_personality 136 -#define SYS_setfsuid 138 -#define SYS_setfsgid 139 -#define SYS__llseek 140 -#define SYS_getdents 141 -#define SYS__newselect 142 -#define SYS_flock 143 -#define SYS_msync 144 -#define SYS_readv 145 -#define SYS_writev 146 -#define SYS_getsid 147 -#define SYS_fdatasync 148 -#define SYS__sysctl 149 -#define SYS_mlock 150 -#define SYS_munlock 151 -#define SYS_mlockall 152 -#define SYS_munlockall 153 -#define SYS_sched_setparam 154 -#define SYS_sched_getparam 155 -#define SYS_sched_setscheduler 156 -#define SYS_sched_getscheduler 157 -#define SYS_sched_yield 158 -#define SYS_sched_get_priority_max 159 -#define SYS_sched_get_priority_min 160 -#define SYS_sched_rr_get_interval 161 -#define SYS_nanosleep 162 -#define SYS_mremap 163 -#define SYS_setresuid 164 -#define SYS_getresuid 165 -#define SYS_poll 168 -#define SYS_nfsservctl 169 -#define SYS_setresgid 170 -#define SYS_getresgid 171 -#define SYS_prctl 172 -#define SYS_rt_sigreturn 173 -#define SYS_rt_sigaction 174 -#define SYS_rt_sigprocmask 175 -#define SYS_rt_sigpending 176 -#define SYS_rt_sigtimedwait 177 -#define SYS_rt_sigqueueinfo 178 -#define SYS_rt_sigsuspend 179 -#define SYS_pread64 180 -#define SYS_pwrite64 181 -#define SYS_chown 182 -#define SYS_getcwd 183 -#define SYS_capget 184 -#define SYS_capset 185 -#define SYS_sigaltstack 186 -#define SYS_sendfile 187 -#define SYS_vfork 190 -#define SYS_ugetrlimit 191 -#define SYS_mmap2 192 -#define SYS_truncate64 193 -#define SYS_ftruncate64 194 -#define SYS_stat64 195 -#define SYS_lstat64 196 -#define SYS_fstat64 197 -#define SYS_lchown32 198 -#define SYS_getuid32 199 -#define SYS_getgid32 200 -#define SYS_geteuid32 201 -#define SYS_getegid32 202 -#define SYS_setreuid32 203 -#define SYS_setregid32 204 -#define SYS_getgroups32 205 -#define SYS_setgroups32 206 -#define SYS_fchown32 207 -#define SYS_setresuid32 208 -#define SYS_getresuid32 209 -#define SYS_setresgid32 210 -#define SYS_getresgid32 211 -#define SYS_chown32 212 -#define SYS_setuid32 213 -#define SYS_setgid32 214 -#define SYS_setfsuid32 215 -#define SYS_setfsgid32 216 -#define SYS_getdents64 217 -#define SYS_pivot_root 218 -#define SYS_mincore 219 -#define SYS_madvise 220 -#define SYS_fcntl64 221 -#define SYS_gettid 224 -#define SYS_readahead 225 -#define SYS_setxattr 226 -#define SYS_lsetxattr 227 -#define SYS_fsetxattr 228 -#define SYS_getxattr 229 -#define SYS_lgetxattr 230 -#define SYS_fgetxattr 231 -#define SYS_listxattr 232 -#define SYS_llistxattr 233 -#define SYS_flistxattr 234 -#define SYS_removexattr 235 -#define SYS_lremovexattr 236 -#define SYS_fremovexattr 237 -#define SYS_tkill 238 -#define SYS_sendfile64 239 -#define SYS_futex 240 -#define SYS_sched_setaffinity 241 -#define SYS_sched_getaffinity 242 -#define SYS_io_setup 243 -#define SYS_io_destroy 244 -#define SYS_io_getevents 245 -#define SYS_io_submit 246 -#define SYS_io_cancel 247 -#define SYS_exit_group 248 -#define SYS_lookup_dcookie 249 -#define SYS_epoll_create 250 -#define SYS_epoll_ctl 251 -#define SYS_epoll_wait 252 -#define SYS_remap_file_pages 253 -#define SYS_set_tid_address 256 -#define SYS_timer_create 257 -#define SYS_timer_settime 258 -#define SYS_timer_gettime 259 -#define SYS_timer_getoverrun 260 -#define SYS_timer_delete 261 -#define SYS_clock_settime 262 -#define SYS_clock_gettime 263 -#define SYS_clock_getres 264 -#define SYS_clock_nanosleep 265 -#define SYS_statfs64 266 -#define SYS_fstatfs64 267 -#define SYS_tgkill 268 -#define SYS_utimes 269 -#define SYS_fadvise64_64 270 -#define SYS_pciconfig_iobase 271 -#define SYS_pciconfig_read 272 -#define SYS_pciconfig_write 273 -#define SYS_mq_open 274 -#define SYS_mq_unlink 275 -#define SYS_mq_timedsend 276 -#define SYS_mq_timedreceive 277 -#define SYS_mq_notify 278 -#define SYS_mq_getsetattr 279 -#define SYS_waitid 280 -#define SYS_socket 281 -#define SYS_bind 282 -#define SYS_connect 283 -#define SYS_listen 284 -#define SYS_accept 285 -#define SYS_getsockname 286 -#define SYS_getpeername 287 -#define SYS_socketpair 288 -#define SYS_send 289 -#define SYS_sendto 290 -#define SYS_recv 291 -#define SYS_recvfrom 292 -#define SYS_shutdown 293 -#define SYS_setsockopt 294 -#define SYS_getsockopt 295 -#define SYS_sendmsg 296 -#define SYS_recvmsg 297 -#define SYS_semop 298 -#define SYS_semget 299 -#define SYS_semctl 300 -#define SYS_msgsnd 301 -#define SYS_msgrcv 302 -#define SYS_msgget 303 -#define SYS_msgctl 304 -#define SYS_shmat 305 -#define SYS_shmdt 306 -#define SYS_shmget 307 -#define SYS_shmctl 308 -#define SYS_add_key 309 -#define SYS_request_key 310 -#define SYS_keyctl 311 -#define SYS_semtimedop 312 -#define SYS_vserver 313 -#define SYS_ioprio_set 314 -#define SYS_ioprio_get 315 -#define SYS_inotify_init 316 -#define SYS_inotify_add_watch 317 -#define SYS_inotify_rm_watch 318 -#define SYS_mbind 319 -#define SYS_get_mempolicy 320 -#define SYS_set_mempolicy 321 -#define SYS_openat 322 -#define SYS_mkdirat 323 -#define SYS_mknodat 324 -#define SYS_fchownat 325 -#define SYS_futimesat 326 -#define SYS_fstatat64 327 -#define SYS_unlinkat 328 -#define SYS_renameat 329 -#define SYS_linkat 330 -#define SYS_symlinkat 331 -#define SYS_readlinkat 332 -#define SYS_fchmodat 333 -#define SYS_faccessat 334 -#define SYS_pselect6 335 -#define SYS_ppoll 336 -#define SYS_unshare 337 -#define SYS_set_robust_list 338 -#define SYS_get_robust_list 339 -#define SYS_splice 340 -#define SYS_sync_file_range2 341 -#define SYS_tee 342 -#define SYS_vmsplice 343 -#define SYS_move_pages 344 -#define SYS_getcpu 345 -#define SYS_epoll_pwait 346 -#define SYS_kexec_load 347 -#define SYS_utimensat 348 -#define SYS_signalfd 349 -#define SYS_timerfd_create 350 -#define SYS_eventfd 351 -#define SYS_fallocate 352 -#define SYS_timerfd_settime 353 -#define SYS_timerfd_gettime 354 -#define SYS_signalfd4 355 -#define SYS_eventfd2 356 -#define SYS_epoll_create1 357 -#define SYS_dup3 358 -#define SYS_pipe2 359 -#define SYS_inotify_init1 360 -#define SYS_preadv 361 -#define SYS_pwritev 362 -#define SYS_rt_tgsigqueueinfo 363 -#define SYS_perf_event_open 364 -#define SYS_recvmmsg 365 -#define SYS_accept4 366 -#define SYS_fanotify_init 367 -#define SYS_fanotify_mark 368 -#define SYS_prlimit64 369 -#define SYS_name_to_handle_at 370 -#define SYS_open_by_handle_at 371 -#define SYS_clock_adjtime 372 -#define SYS_syncfs 373 -#define SYS_sendmmsg 374 -#define SYS_setns 375 -#define SYS_process_vm_readv 376 -#define SYS_process_vm_writev 377 -#define SYS_kcmp 378 -#define SYS_finit_module 379 diff --git a/user/include/bits/termios.h b/user/include/bits/termios.h deleted file mode 100644 index f0d81b13..00000000 --- a/user/include/bits/termios.h +++ /dev/null @@ -1,160 +0,0 @@ -struct termios -{ - tcflag_t c_iflag; - tcflag_t c_oflag; - tcflag_t c_cflag; - tcflag_t c_lflag; - cc_t c_line; - cc_t c_cc[NCCS]; - speed_t __c_ispeed; - speed_t __c_ospeed; -}; - -#define VINTR 0 -#define VQUIT 1 -#define VERASE 2 -#define VKILL 3 -#define VEOF 4 -#define VTIME 5 -#define VMIN 6 -#define VSWTC 7 -#define VSTART 8 -#define VSTOP 9 -#define VSUSP 10 -#define VEOL 11 -#define VREPRINT 12 -#define VDISCARD 13 -#define VWERASE 14 -#define VLNEXT 15 -#define VEOL2 16 - -#define IGNBRK 0000001 -#define BRKINT 0000002 -#define IGNPAR 0000004 -#define PARMRK 0000010 -#define INPCK 0000020 -#define ISTRIP 0000040 -#define INLCR 0000100 -#define IGNCR 0000200 -#define ICRNL 0000400 -#define IUCLC 0001000 -#define IXON 0002000 -#define IXANY 0004000 -#define IXOFF 0010000 -#define IMAXBEL 0020000 -#define IUTF8 0040000 - -#define OPOST 0000001 -#define OLCUC 0000002 -#define ONLCR 0000004 -#define OCRNL 0000010 -#define ONOCR 0000020 -#define ONLRET 0000040 -#define OFILL 0000100 -#define OFDEL 0000200 -#define NLDLY 0000400 -#define NL0 0000000 -#define NL1 0000400 -#define CRDLY 0003000 -#define CR0 0000000 -#define CR1 0001000 -#define CR2 0002000 -#define CR3 0003000 -#define TABDLY 0014000 -#define TAB0 0000000 -#define TAB1 0004000 -#define TAB2 0010000 -#define TAB3 0014000 -#define BSDLY 0020000 -#define BS0 0000000 -#define BS1 0020000 -#define FFDLY 0100000 -#define FF0 0000000 -#define FF1 0100000 - -#define VTDLY 0040000 -#define VT0 0000000 -#define VT1 0040000 - -#define B0 0000000 -#define B50 0000001 -#define B75 0000002 -#define B110 0000003 -#define B134 0000004 -#define B150 0000005 -#define B200 0000006 -#define B300 0000007 -#define B600 0000010 -#define B1200 0000011 -#define B1800 0000012 -#define B2400 0000013 -#define B4800 0000014 -#define B9600 0000015 -#define B19200 0000016 -#define B38400 0000017 - -#define B57600 0010001 -#define B115200 0010002 -#define B230400 0010003 -#define B460800 0010004 -#define B500000 0010005 -#define B576000 0010006 -#define B921600 0010007 -#define B1000000 0010010 -#define B1152000 0010011 -#define B1500000 0010012 -#define B2000000 0010013 -#define B2500000 0010014 -#define B3000000 0010015 -#define B3500000 0010016 -#define B4000000 0010017 - -#define CBAUD 0010017 - -#define CSIZE 0000060 -#define CS5 0000000 -#define CS6 0000020 -#define CS7 0000040 -#define CS8 0000060 -#define CSTOPB 0000100 -#define CREAD 0000200 -#define PARENB 0000400 -#define PARODD 0001000 -#define HUPCL 0002000 -#define CLOCAL 0004000 - -#define ISIG 0000001 -#define ICANON 0000002 -#define ECHO 0000010 -#define ECHOE 0000020 -#define ECHOK 0000040 -#define ECHONL 0000100 -#define NOFLSH 0000200 -#define TOSTOP 0000400 -#define IEXTEN 0100000 - -#define ECHOCTL 0001000 -#define ECHOPRT 0002000 -#define ECHOKE 0004000 -#define FLUSHO 0010000 -#define PENDIN 0040000 - -#define TCOOFF 0 -#define TCOON 1 -#define TCIOFF 2 -#define TCION 3 - -#define TCIFLUSH 0 -#define TCOFLUSH 1 -#define TCIOFLUSH 2 - -#define TCSANOW 0 -#define TCSADRAIN 1 -#define TCSAFLUSH 2 - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define CBAUDEX 0010000 -#define CRTSCTS 020000000000 -#define EXTPROC 0200000 -#define XTABS 0014000 -#endif diff --git a/user/include/complex.h b/user/include/complex.h deleted file mode 100644 index 13a45c57..00000000 --- a/user/include/complex.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef _COMPLEX_H -#define _COMPLEX_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define complex _Complex -#ifdef __GNUC__ -#define _Complex_I (__extension__ 1.0fi) -#else -#define _Complex_I 1.0fi -#endif -#define I _Complex_I - -double complex cacos(double complex); -float complex cacosf(float complex); -long double complex cacosl(long double complex); - -double complex casin(double complex); -float complex casinf(float complex); -long double complex casinl(long double complex); - -double complex catan(double complex); -float complex catanf(float complex); -long double complex catanl(long double complex); - -double complex ccos(double complex); -float complex ccosf(float complex); -long double complex ccosl(long double complex); - -double complex csin(double complex); -float complex csinf(float complex); -long double complex csinl(long double complex); - -double complex ctan(double complex); -float complex ctanf(float complex); -long double complex ctanl(long double complex); - -double complex cacosh(double complex); -float complex cacoshf(float complex); -long double complex cacoshl(long double complex); - -double complex casinh(double complex); -float complex casinhf(float complex); -long double complex casinhl(long double complex); - -double complex catanh(double complex); -float complex catanhf(float complex); -long double complex catanhl(long double complex); - -double complex ccosh(double complex); -float complex ccoshf(float complex); -long double complex ccoshl(long double complex); - -double complex csinh(double complex); -float complex csinhf(float complex); -long double complex csinhl(long double complex); - -double complex ctanh(double complex); -float complex ctanhf(float complex); -long double complex ctanhl(long double complex); - -double complex cexp(double complex); -float complex cexpf(float complex); -long double complex cexpl(long double complex); - -double complex clog(double complex); -float complex clogf(float complex); -long double complex clogl(long double complex); - -double cabs(double complex); -float cabsf(float complex); -long double cabsl(long double complex); - -double complex cpow(double complex, double complex); -float complex cpowf(float complex, float complex); -long double complex cpowl(long double complex, long double complex); - -double complex csqrt(double complex); -float complex csqrtf(float complex); -long double complex csqrtl(long double complex); - -double carg(double complex); -float cargf(float complex); -long double cargl(long double complex); - -double cimag(double complex); -float cimagf(float complex); -long double cimagl(long double complex); - -double complex conj(double complex); -float complex conjf(float complex); -long double complex conjl(long double complex); - -double complex cproj(double complex); -float complex cprojf(float complex); -long double complex cprojl(long double complex); - -double creal(double complex); -float crealf(float complex); -long double creall(long double complex); - -#define __CIMAG(x, t) \ - ((union { _Complex t __z; t __xy[2]; }){(_Complex t)(x)}.__xy[1]) - -#define creal(x) ((double)(x)) -#define crealf(x) ((float)(x)) -#define creall(x) ((long double)(x)) - -#define cimag(x) __CIMAG(x, double) -#define cimagf(x) __CIMAG(x, float) -#define cimagl(x) __CIMAG(x, long double) - -#define __CMPLX(x, y, t) \ - ((union { _Complex t __z; t __xy[2]; }){.__xy = {(x),(y)}}.__z) - -#define CMPLX(x, y) __CMPLX(x, y, double) -#define CMPLXF(x, y) __CMPLX(x, y, float) -#define CMPLXL(x, y) __CMPLX(x, y, long double) - -#ifdef __cplusplus -} -#endif -#endif diff --git a/user/include/ctype.h b/user/include/ctype.h deleted file mode 100644 index 8f0d1687..00000000 --- a/user/include/ctype.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _CTYPE_H -#define _CTYPE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -int isalnum(int); -int isalpha(int); -int isblank(int); -int iscntrl(int); -int isdigit(int); -int isgraph(int); -int islower(int); -int isprint(int); -int ispunct(int); -int isspace(int); -int isupper(int); -int isxdigit(int); -int tolower(int); -int toupper(int); - -#define isalpha(a) ((((unsigned)(a)|32)-'a') < 26) -#define isdigit(a) (((unsigned)(a)-'0') < 10) -#define islower(a) (((unsigned)(a)-'a') < 26) -#define isupper(a) (((unsigned)(a)-'A') < 26) -#define isprint(a) (((unsigned)(a)-0x20) < 0x5f) -#define isgraph(a) (((unsigned)(a)-0x21) < 0x5e) - - - -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ - || defined(_BSD_SOURCE) - -#define __NEED_locale_t -#include - -int isalnum_l(int, locale_t); -int isalpha_l(int, locale_t); -int isblank_l(int, locale_t); -int iscntrl_l(int, locale_t); -int isdigit_l(int, locale_t); -int isgraph_l(int, locale_t); -int islower_l(int, locale_t); -int isprint_l(int, locale_t); -int ispunct_l(int, locale_t); -int isspace_l(int, locale_t); -int isupper_l(int, locale_t); -int isxdigit_l(int, locale_t); -int tolower_l(int, locale_t); -int toupper_l(int, locale_t); - -int isascii(int); -int toascii(int); -#define _tolower(a) ((a)|0x20) -#define _toupper(a) ((a)&0x5f) - -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/user/include/elf.h b/user/include/elf.h deleted file mode 100644 index 4d8c0c8e..00000000 --- a/user/include/elf.h +++ /dev/null @@ -1,2783 +0,0 @@ -#ifndef _ELF_H -#define _ELF_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -typedef uint16_t Elf32_Half; -typedef uint16_t Elf64_Half; - -typedef uint32_t Elf32_Word; -typedef int32_t Elf32_Sword; -typedef uint32_t Elf64_Word; -typedef int32_t Elf64_Sword; - -typedef uint64_t Elf32_Xword; -typedef int64_t Elf32_Sxword; -typedef uint64_t Elf64_Xword; -typedef int64_t Elf64_Sxword; - -typedef uint32_t Elf32_Addr; -typedef uint64_t Elf64_Addr; - -typedef uint32_t Elf32_Off; -typedef uint64_t Elf64_Off; - -typedef uint16_t Elf32_Section; -typedef uint16_t Elf64_Section; - -typedef Elf32_Half Elf32_Versym; -typedef Elf64_Half Elf64_Versym; - -#define EI_NIDENT (16) - -typedef struct { - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -} Elf32_Ehdr; - -typedef struct { - unsigned char e_ident[EI_NIDENT]; - Elf64_Half e_type; - Elf64_Half e_machine; - Elf64_Word e_version; - Elf64_Addr e_entry; - Elf64_Off e_phoff; - Elf64_Off e_shoff; - Elf64_Word e_flags; - Elf64_Half e_ehsize; - Elf64_Half e_phentsize; - Elf64_Half e_phnum; - Elf64_Half e_shentsize; - Elf64_Half e_shnum; - Elf64_Half e_shstrndx; -} Elf64_Ehdr; - -#define EI_MAG0 0 -#define ELFMAG0 0x7f - -#define EI_MAG1 1 -#define ELFMAG1 'E' - -#define EI_MAG2 2 -#define ELFMAG2 'L' - -#define EI_MAG3 3 -#define ELFMAG3 'F' - - -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -#define EI_CLASS 4 -#define ELFCLASSNONE 0 -#define ELFCLASS32 1 -#define ELFCLASS64 2 -#define ELFCLASSNUM 3 - -#define EI_DATA 5 -#define ELFDATANONE 0 -#define ELFDATA2LSB 1 -#define ELFDATA2MSB 2 -#define ELFDATANUM 3 - -#define EI_VERSION 6 - - -#define EI_OSABI 7 -#define ELFOSABI_NONE 0 -#define ELFOSABI_SYSV 0 -#define ELFOSABI_HPUX 1 -#define ELFOSABI_NETBSD 2 -#define ELFOSABI_LINUX 3 -#define ELFOSABI_GNU 3 -#define ELFOSABI_SOLARIS 6 -#define ELFOSABI_AIX 7 -#define ELFOSABI_IRIX 8 -#define ELFOSABI_FREEBSD 9 -#define ELFOSABI_TRU64 10 -#define ELFOSABI_MODESTO 11 -#define ELFOSABI_OPENBSD 12 -#define ELFOSABI_ARM 97 -#define ELFOSABI_STANDALONE 255 - -#define EI_ABIVERSION 8 - -#define EI_PAD 9 - - - -#define ET_NONE 0 -#define ET_REL 1 -#define ET_EXEC 2 -#define ET_DYN 3 -#define ET_CORE 4 -#define ET_NUM 5 -#define ET_LOOS 0xfe00 -#define ET_HIOS 0xfeff -#define ET_LOPROC 0xff00 -#define ET_HIPROC 0xffff - - - -#define EM_NONE 0 -#define EM_M32 1 -#define EM_SPARC 2 -#define EM_386 3 -#define EM_68K 4 -#define EM_88K 5 -#define EM_860 7 -#define EM_MIPS 8 -#define EM_S370 9 -#define EM_MIPS_RS3_LE 10 - -#define EM_PARISC 15 -#define EM_VPP500 17 -#define EM_SPARC32PLUS 18 -#define EM_960 19 -#define EM_PPC 20 -#define EM_PPC64 21 -#define EM_S390 22 - -#define EM_V800 36 -#define EM_FR20 37 -#define EM_RH32 38 -#define EM_RCE 39 -#define EM_ARM 40 -#define EM_FAKE_ALPHA 41 -#define EM_SH 42 -#define EM_SPARCV9 43 -#define EM_TRICORE 44 -#define EM_ARC 45 -#define EM_H8_300 46 -#define EM_H8_300H 47 -#define EM_H8S 48 -#define EM_H8_500 49 -#define EM_IA_64 50 -#define EM_MIPS_X 51 -#define EM_COLDFIRE 52 -#define EM_68HC12 53 -#define EM_MMA 54 -#define EM_PCP 55 -#define EM_NCPU 56 -#define EM_NDR1 57 -#define EM_STARCORE 58 -#define EM_ME16 59 -#define EM_ST100 60 -#define EM_TINYJ 61 -#define EM_X86_64 62 -#define EM_PDSP 63 - -#define EM_FX66 66 -#define EM_ST9PLUS 67 -#define EM_ST7 68 -#define EM_68HC16 69 -#define EM_68HC11 70 -#define EM_68HC08 71 -#define EM_68HC05 72 -#define EM_SVX 73 -#define EM_ST19 74 -#define EM_VAX 75 -#define EM_CRIS 76 -#define EM_JAVELIN 77 -#define EM_FIREPATH 78 -#define EM_ZSP 79 -#define EM_MMIX 80 -#define EM_HUANY 81 -#define EM_PRISM 82 -#define EM_AVR 83 -#define EM_FR30 84 -#define EM_D10V 85 -#define EM_D30V 86 -#define EM_V850 87 -#define EM_M32R 88 -#define EM_MN10300 89 -#define EM_MN10200 90 -#define EM_PJ 91 -#define EM_OPENRISC 92 -#define EM_ARC_A5 93 -#define EM_XTENSA 94 -#define EM_AARCH64 183 -#define EM_TILEPRO 188 -#define EM_MICROBLAZE 189 -#define EM_TILEGX 191 -#define EM_NUM 192 -#define EM_ALPHA 0x9026 - -#define EV_NONE 0 -#define EV_CURRENT 1 -#define EV_NUM 2 - -typedef struct { - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; - -typedef struct { - Elf64_Word sh_name; - Elf64_Word sh_type; - Elf64_Xword sh_flags; - Elf64_Addr sh_addr; - Elf64_Off sh_offset; - Elf64_Xword sh_size; - Elf64_Word sh_link; - Elf64_Word sh_info; - Elf64_Xword sh_addralign; - Elf64_Xword sh_entsize; -} Elf64_Shdr; - - - -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xff00 -#define SHN_LOPROC 0xff00 -#define SHN_BEFORE 0xff00 - -#define SHN_AFTER 0xff01 - -#define SHN_HIPROC 0xff1f -#define SHN_LOOS 0xff20 -#define SHN_HIOS 0xff3f -#define SHN_ABS 0xfff1 -#define SHN_COMMON 0xfff2 -#define SHN_XINDEX 0xffff -#define SHN_HIRESERVE 0xffff - - - -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 -#define SHT_INIT_ARRAY 14 -#define SHT_FINI_ARRAY 15 -#define SHT_PREINIT_ARRAY 16 -#define SHT_GROUP 17 -#define SHT_SYMTAB_SHNDX 18 -#define SHT_NUM 19 -#define SHT_LOOS 0x60000000 -#define SHT_GNU_ATTRIBUTES 0x6ffffff5 -#define SHT_GNU_HASH 0x6ffffff6 -#define SHT_GNU_LIBLIST 0x6ffffff7 -#define SHT_CHECKSUM 0x6ffffff8 -#define SHT_LOSUNW 0x6ffffffa -#define SHT_SUNW_move 0x6ffffffa -#define SHT_SUNW_COMDAT 0x6ffffffb -#define SHT_SUNW_syminfo 0x6ffffffc -#define SHT_GNU_verdef 0x6ffffffd -#define SHT_GNU_verneed 0x6ffffffe -#define SHT_GNU_versym 0x6fffffff -#define SHT_HISUNW 0x6fffffff -#define SHT_HIOS 0x6fffffff -#define SHT_LOPROC 0x70000000 -#define SHT_HIPROC 0x7fffffff -#define SHT_LOUSER 0x80000000 -#define SHT_HIUSER 0x8fffffff - -#define SHF_WRITE (1 << 0) -#define SHF_ALLOC (1 << 1) -#define SHF_EXECINSTR (1 << 2) -#define SHF_MERGE (1 << 4) -#define SHF_STRINGS (1 << 5) -#define SHF_INFO_LINK (1 << 6) -#define SHF_LINK_ORDER (1 << 7) -#define SHF_OS_NONCONFORMING (1 << 8) - -#define SHF_GROUP (1 << 9) -#define SHF_TLS (1 << 10) -#define SHF_MASKOS 0x0ff00000 -#define SHF_MASKPROC 0xf0000000 -#define SHF_ORDERED (1 << 30) -#define SHF_EXCLUDE (1 << 31) - -#define GRP_COMDAT 0x1 - -typedef struct { - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; - unsigned char st_info; - unsigned char st_other; - Elf32_Section st_shndx; -} Elf32_Sym; - -typedef struct { - Elf64_Word st_name; - unsigned char st_info; - unsigned char st_other; - Elf64_Section st_shndx; - Elf64_Addr st_value; - Elf64_Xword st_size; -} Elf64_Sym; - -typedef struct { - Elf32_Half si_boundto; - Elf32_Half si_flags; -} Elf32_Syminfo; - -typedef struct { - Elf64_Half si_boundto; - Elf64_Half si_flags; -} Elf64_Syminfo; - -#define SYMINFO_BT_SELF 0xffff -#define SYMINFO_BT_PARENT 0xfffe -#define SYMINFO_BT_LOWRESERVE 0xff00 - -#define SYMINFO_FLG_DIRECT 0x0001 -#define SYMINFO_FLG_PASSTHRU 0x0002 -#define SYMINFO_FLG_COPY 0x0004 -#define SYMINFO_FLG_LAZYLOAD 0x0008 - -#define SYMINFO_NONE 0 -#define SYMINFO_CURRENT 1 -#define SYMINFO_NUM 2 - -#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) -#define ELF32_ST_TYPE(val) ((val) & 0xf) -#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) - -#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) -#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) -#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) - -#define STB_LOCAL 0 -#define STB_GLOBAL 1 -#define STB_WEAK 2 -#define STB_NUM 3 -#define STB_LOOS 10 -#define STB_GNU_UNIQUE 10 -#define STB_HIOS 12 -#define STB_LOPROC 13 -#define STB_HIPROC 15 - -#define STT_NOTYPE 0 -#define STT_OBJECT 1 -#define STT_FUNC 2 -#define STT_SECTION 3 -#define STT_FILE 4 -#define STT_COMMON 5 -#define STT_TLS 6 -#define STT_NUM 7 -#define STT_LOOS 10 -#define STT_GNU_IFUNC 10 -#define STT_HIOS 12 -#define STT_LOPROC 13 -#define STT_HIPROC 15 - -#define STN_UNDEF 0 - -#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) -#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) - -#define STV_DEFAULT 0 -#define STV_INTERNAL 1 -#define STV_HIDDEN 2 -#define STV_PROTECTED 3 - - - - -typedef struct -{ - Elf32_Addr r_offset; - Elf32_Word r_info; -} Elf32_Rel; - -typedef struct { - Elf64_Addr r_offset; - Elf64_Xword r_info; -} Elf64_Rel; - - - -typedef struct { - Elf32_Addr r_offset; - Elf32_Word r_info; - Elf32_Sword r_addend; -} Elf32_Rela; - -typedef struct { - Elf64_Addr r_offset; - Elf64_Xword r_info; - Elf64_Sxword r_addend; -} Elf64_Rela; - - - -#define ELF32_R_SYM(val) ((val) >> 8) -#define ELF32_R_TYPE(val) ((val) & 0xff) -#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) - -#define ELF64_R_SYM(i) ((i) >> 32) -#define ELF64_R_TYPE(i) ((i) & 0xffffffff) -#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) - - - -typedef struct { - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -} Elf32_Phdr; - -typedef struct { - Elf64_Word p_type; - Elf64_Word p_flags; - Elf64_Off p_offset; - Elf64_Addr p_vaddr; - Elf64_Addr p_paddr; - Elf64_Xword p_filesz; - Elf64_Xword p_memsz; - Elf64_Xword p_align; -} Elf64_Phdr; - - - -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_TLS 7 -#define PT_NUM 8 -#define PT_LOOS 0x60000000 -#define PT_GNU_EH_FRAME 0x6474e550 -#define PT_GNU_STACK 0x6474e551 -#define PT_GNU_RELRO 0x6474e552 -#define PT_LOSUNW 0x6ffffffa -#define PT_SUNWBSS 0x6ffffffa -#define PT_SUNWSTACK 0x6ffffffb -#define PT_HISUNW 0x6fffffff -#define PT_HIOS 0x6fffffff -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff - - -#define PN_XNUM 0xffff - - -#define PF_X (1 << 0) -#define PF_W (1 << 1) -#define PF_R (1 << 2) -#define PF_MASKOS 0x0ff00000 -#define PF_MASKPROC 0xf0000000 - - - -#define NT_PRSTATUS 1 -#define NT_FPREGSET 2 -#define NT_PRPSINFO 3 -#define NT_PRXREG 4 -#define NT_TASKSTRUCT 4 -#define NT_PLATFORM 5 -#define NT_AUXV 6 -#define NT_GWINDOWS 7 -#define NT_ASRS 8 -#define NT_PSTATUS 10 -#define NT_PSINFO 13 -#define NT_PRCRED 14 -#define NT_UTSNAME 15 -#define NT_LWPSTATUS 16 -#define NT_LWPSINFO 17 -#define NT_PRFPXREG 20 -#define NT_SIGINFO 0x53494749 -#define NT_FILE 0x46494c45 -#define NT_PRXFPREG 0x46e62b7f -#define NT_PPC_VMX 0x100 -#define NT_PPC_SPE 0x101 -#define NT_PPC_VSX 0x102 -#define NT_386_TLS 0x200 -#define NT_386_IOPERM 0x201 -#define NT_X86_XSTATE 0x202 -#define NT_S390_HIGH_GPRS 0x300 -#define NT_S390_TIMER 0x301 -#define NT_S390_TODCMP 0x302 -#define NT_S390_TODPREG 0x303 -#define NT_S390_CTRS 0x304 -#define NT_S390_PREFIX 0x305 -#define NT_S390_LAST_BREAK 0x306 -#define NT_S390_SYSTEM_CALL 0x307 -#define NT_S390_TDB 0x308 -#define NT_ARM_VFP 0x400 -#define NT_ARM_TLS 0x401 -#define NT_ARM_HW_BREAK 0x402 -#define NT_ARM_HW_WATCH 0x403 -#define NT_METAG_CBUF 0x500 -#define NT_METAG_RPIPE 0x501 -#define NT_METAG_TLS 0x502 -#define NT_VERSION 1 - - - - -typedef struct { - Elf32_Sword d_tag; - union { - Elf32_Word d_val; - Elf32_Addr d_ptr; - } d_un; -} Elf32_Dyn; - -typedef struct { - Elf64_Sxword d_tag; - union { - Elf64_Xword d_val; - Elf64_Addr d_ptr; - } d_un; -} Elf64_Dyn; - - - -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 -#define DT_PLTGOT 3 -#define DT_HASH 4 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_RELA 7 -#define DT_RELASZ 8 -#define DT_RELAENT 9 -#define DT_STRSZ 10 -#define DT_SYMENT 11 -#define DT_INIT 12 -#define DT_FINI 13 -#define DT_SONAME 14 -#define DT_RPATH 15 -#define DT_SYMBOLIC 16 -#define DT_REL 17 -#define DT_RELSZ 18 -#define DT_RELENT 19 -#define DT_PLTREL 20 -#define DT_DEBUG 21 -#define DT_TEXTREL 22 -#define DT_JMPREL 23 -#define DT_BIND_NOW 24 -#define DT_INIT_ARRAY 25 -#define DT_FINI_ARRAY 26 -#define DT_INIT_ARRAYSZ 27 -#define DT_FINI_ARRAYSZ 28 -#define DT_RUNPATH 29 -#define DT_FLAGS 30 -#define DT_ENCODING 32 -#define DT_PREINIT_ARRAY 32 -#define DT_PREINIT_ARRAYSZ 33 -#define DT_NUM 34 -#define DT_LOOS 0x6000000d -#define DT_HIOS 0x6ffff000 -#define DT_LOPROC 0x70000000 -#define DT_HIPROC 0x7fffffff -#define DT_PROCNUM DT_MIPS_NUM - -#define DT_VALRNGLO 0x6ffffd00 -#define DT_GNU_PRELINKED 0x6ffffdf5 -#define DT_GNU_CONFLICTSZ 0x6ffffdf6 -#define DT_GNU_LIBLISTSZ 0x6ffffdf7 -#define DT_CHECKSUM 0x6ffffdf8 -#define DT_PLTPADSZ 0x6ffffdf9 -#define DT_MOVEENT 0x6ffffdfa -#define DT_MOVESZ 0x6ffffdfb -#define DT_FEATURE_1 0x6ffffdfc -#define DT_POSFLAG_1 0x6ffffdfd - -#define DT_SYMINSZ 0x6ffffdfe -#define DT_SYMINENT 0x6ffffdff -#define DT_VALRNGHI 0x6ffffdff -#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) -#define DT_VALNUM 12 - -#define DT_ADDRRNGLO 0x6ffffe00 -#define DT_GNU_HASH 0x6ffffef5 -#define DT_TLSDESC_PLT 0x6ffffef6 -#define DT_TLSDESC_GOT 0x6ffffef7 -#define DT_GNU_CONFLICT 0x6ffffef8 -#define DT_GNU_LIBLIST 0x6ffffef9 -#define DT_CONFIG 0x6ffffefa -#define DT_DEPAUDIT 0x6ffffefb -#define DT_AUDIT 0x6ffffefc -#define DT_PLTPAD 0x6ffffefd -#define DT_MOVETAB 0x6ffffefe -#define DT_SYMINFO 0x6ffffeff -#define DT_ADDRRNGHI 0x6ffffeff -#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) -#define DT_ADDRNUM 11 - - - -#define DT_VERSYM 0x6ffffff0 - -#define DT_RELACOUNT 0x6ffffff9 -#define DT_RELCOUNT 0x6ffffffa - - -#define DT_FLAGS_1 0x6ffffffb -#define DT_VERDEF 0x6ffffffc - -#define DT_VERDEFNUM 0x6ffffffd -#define DT_VERNEED 0x6ffffffe - -#define DT_VERNEEDNUM 0x6fffffff -#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) -#define DT_VERSIONTAGNUM 16 - - - -#define DT_AUXILIARY 0x7ffffffd -#define DT_FILTER 0x7fffffff -#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) -#define DT_EXTRANUM 3 - - -#define DF_ORIGIN 0x00000001 -#define DF_SYMBOLIC 0x00000002 -#define DF_TEXTREL 0x00000004 -#define DF_BIND_NOW 0x00000008 -#define DF_STATIC_TLS 0x00000010 - - - -#define DF_1_NOW 0x00000001 -#define DF_1_GLOBAL 0x00000002 -#define DF_1_GROUP 0x00000004 -#define DF_1_NODELETE 0x00000008 -#define DF_1_LOADFLTR 0x00000010 -#define DF_1_INITFIRST 0x00000020 -#define DF_1_NOOPEN 0x00000040 -#define DF_1_ORIGIN 0x00000080 -#define DF_1_DIRECT 0x00000100 -#define DF_1_TRANS 0x00000200 -#define DF_1_INTERPOSE 0x00000400 -#define DF_1_NODEFLIB 0x00000800 -#define DF_1_NODUMP 0x00001000 -#define DF_1_CONFALT 0x00002000 -#define DF_1_ENDFILTEE 0x00004000 -#define DF_1_DISPRELDNE 0x00008000 -#define DF_1_DISPRELPND 0x00010000 -#define DF_1_NODIRECT 0x00020000 -#define DF_1_IGNMULDEF 0x00040000 -#define DF_1_NOKSYMS 0x00080000 -#define DF_1_NOHDR 0x00100000 -#define DF_1_EDITED 0x00200000 -#define DF_1_NORELOC 0x00400000 -#define DF_1_SYMINTPOSE 0x00800000 -#define DF_1_GLOBAUDIT 0x01000000 -#define DF_1_SINGLETON 0x02000000 - -#define DTF_1_PARINIT 0x00000001 -#define DTF_1_CONFEXP 0x00000002 - - -#define DF_P1_LAZYLOAD 0x00000001 -#define DF_P1_GROUPPERM 0x00000002 - - - - -typedef struct { - Elf32_Half vd_version; - Elf32_Half vd_flags; - Elf32_Half vd_ndx; - Elf32_Half vd_cnt; - Elf32_Word vd_hash; - Elf32_Word vd_aux; - Elf32_Word vd_next; -} Elf32_Verdef; - -typedef struct { - Elf64_Half vd_version; - Elf64_Half vd_flags; - Elf64_Half vd_ndx; - Elf64_Half vd_cnt; - Elf64_Word vd_hash; - Elf64_Word vd_aux; - Elf64_Word vd_next; -} Elf64_Verdef; - - - -#define VER_DEF_NONE 0 -#define VER_DEF_CURRENT 1 -#define VER_DEF_NUM 2 - - -#define VER_FLG_BASE 0x1 -#define VER_FLG_WEAK 0x2 - - -#define VER_NDX_LOCAL 0 -#define VER_NDX_GLOBAL 1 -#define VER_NDX_LORESERVE 0xff00 -#define VER_NDX_ELIMINATE 0xff01 - - - -typedef struct { - Elf32_Word vda_name; - Elf32_Word vda_next; -} Elf32_Verdaux; - -typedef struct { - Elf64_Word vda_name; - Elf64_Word vda_next; -} Elf64_Verdaux; - - - - -typedef struct { - Elf32_Half vn_version; - Elf32_Half vn_cnt; - Elf32_Word vn_file; - Elf32_Word vn_aux; - Elf32_Word vn_next; -} Elf32_Verneed; - -typedef struct { - Elf64_Half vn_version; - Elf64_Half vn_cnt; - Elf64_Word vn_file; - Elf64_Word vn_aux; - Elf64_Word vn_next; -} Elf64_Verneed; - - - -#define VER_NEED_NONE 0 -#define VER_NEED_CURRENT 1 -#define VER_NEED_NUM 2 - - - -typedef struct { - Elf32_Word vna_hash; - Elf32_Half vna_flags; - Elf32_Half vna_other; - Elf32_Word vna_name; - Elf32_Word vna_next; -} Elf32_Vernaux; - -typedef struct { - Elf64_Word vna_hash; - Elf64_Half vna_flags; - Elf64_Half vna_other; - Elf64_Word vna_name; - Elf64_Word vna_next; -} Elf64_Vernaux; - - - -#define VER_FLG_WEAK 0x2 - - - -typedef struct { - uint32_t a_type; - union { - uint32_t a_val; - } a_un; -} Elf32_auxv_t; - -typedef struct { - uint64_t a_type; - union { - uint64_t a_val; - } a_un; -} Elf64_auxv_t; - - - -#define AT_NULL 0 -#define AT_IGNORE 1 -#define AT_EXECFD 2 -#define AT_PHDR 3 -#define AT_PHENT 4 -#define AT_PHNUM 5 -#define AT_PAGESZ 6 -#define AT_BASE 7 -#define AT_FLAGS 8 -#define AT_ENTRY 9 -#define AT_NOTELF 10 -#define AT_UID 11 -#define AT_EUID 12 -#define AT_GID 13 -#define AT_EGID 14 -#define AT_CLKTCK 17 - - -#define AT_PLATFORM 15 -#define AT_HWCAP 16 - - - - -#define AT_FPUCW 18 - - -#define AT_DCACHEBSIZE 19 -#define AT_ICACHEBSIZE 20 -#define AT_UCACHEBSIZE 21 - - - -#define AT_IGNOREPPC 22 - -#define AT_SECURE 23 - -#define AT_BASE_PLATFORM 24 - -#define AT_RANDOM 25 - -#define AT_HWCAP2 26 - -#define AT_EXECFN 31 - - - -#define AT_SYSINFO 32 -#define AT_SYSINFO_EHDR 33 - - - -#define AT_L1I_CACHESHAPE 34 -#define AT_L1D_CACHESHAPE 35 -#define AT_L2_CACHESHAPE 36 -#define AT_L3_CACHESHAPE 37 - - - - -typedef struct { - Elf32_Word n_namesz; - Elf32_Word n_descsz; - Elf32_Word n_type; -} Elf32_Nhdr; - -typedef struct { - Elf64_Word n_namesz; - Elf64_Word n_descsz; - Elf64_Word n_type; -} Elf64_Nhdr; - - - - -#define ELF_NOTE_SOLARIS "SUNW Solaris" - - -#define ELF_NOTE_GNU "GNU" - - - - - -#define ELF_NOTE_PAGESIZE_HINT 1 - - -#define NT_GNU_ABI_TAG 1 -#define ELF_NOTE_ABI NT_GNU_ABI_TAG - - - -#define ELF_NOTE_OS_LINUX 0 -#define ELF_NOTE_OS_GNU 1 -#define ELF_NOTE_OS_SOLARIS2 2 -#define ELF_NOTE_OS_FREEBSD 3 - -#define NT_GNU_BUILD_ID 3 -#define NT_GNU_GOLD_VERSION 4 - - - -typedef struct { - Elf32_Xword m_value; - Elf32_Word m_info; - Elf32_Word m_poffset; - Elf32_Half m_repeat; - Elf32_Half m_stride; -} Elf32_Move; - -typedef struct { - Elf64_Xword m_value; - Elf64_Xword m_info; - Elf64_Xword m_poffset; - Elf64_Half m_repeat; - Elf64_Half m_stride; -} Elf64_Move; - - -#define ELF32_M_SYM(info) ((info) >> 8) -#define ELF32_M_SIZE(info) ((unsigned char) (info)) -#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) - -#define ELF64_M_SYM(info) ELF32_M_SYM (info) -#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) -#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) - -#define EF_CPU32 0x00810000 - -#define R_68K_NONE 0 -#define R_68K_32 1 -#define R_68K_16 2 -#define R_68K_8 3 -#define R_68K_PC32 4 -#define R_68K_PC16 5 -#define R_68K_PC8 6 -#define R_68K_GOT32 7 -#define R_68K_GOT16 8 -#define R_68K_GOT8 9 -#define R_68K_GOT32O 10 -#define R_68K_GOT16O 11 -#define R_68K_GOT8O 12 -#define R_68K_PLT32 13 -#define R_68K_PLT16 14 -#define R_68K_PLT8 15 -#define R_68K_PLT32O 16 -#define R_68K_PLT16O 17 -#define R_68K_PLT8O 18 -#define R_68K_COPY 19 -#define R_68K_GLOB_DAT 20 -#define R_68K_JMP_SLOT 21 -#define R_68K_RELATIVE 22 -#define R_68K_NUM 23 - -#define R_386_NONE 0 -#define R_386_32 1 -#define R_386_PC32 2 -#define R_386_GOT32 3 -#define R_386_PLT32 4 -#define R_386_COPY 5 -#define R_386_GLOB_DAT 6 -#define R_386_JMP_SLOT 7 -#define R_386_RELATIVE 8 -#define R_386_GOTOFF 9 -#define R_386_GOTPC 10 -#define R_386_32PLT 11 -#define R_386_TLS_TPOFF 14 -#define R_386_TLS_IE 15 -#define R_386_TLS_GOTIE 16 -#define R_386_TLS_LE 17 -#define R_386_TLS_GD 18 -#define R_386_TLS_LDM 19 -#define R_386_16 20 -#define R_386_PC16 21 -#define R_386_8 22 -#define R_386_PC8 23 -#define R_386_TLS_GD_32 24 -#define R_386_TLS_GD_PUSH 25 -#define R_386_TLS_GD_CALL 26 -#define R_386_TLS_GD_POP 27 -#define R_386_TLS_LDM_32 28 -#define R_386_TLS_LDM_PUSH 29 -#define R_386_TLS_LDM_CALL 30 -#define R_386_TLS_LDM_POP 31 -#define R_386_TLS_LDO_32 32 -#define R_386_TLS_IE_32 33 -#define R_386_TLS_LE_32 34 -#define R_386_TLS_DTPMOD32 35 -#define R_386_TLS_DTPOFF32 36 -#define R_386_TLS_TPOFF32 37 -#define R_386_SIZE32 38 -#define R_386_TLS_GOTDESC 39 -#define R_386_TLS_DESC_CALL 40 -#define R_386_TLS_DESC 41 -#define R_386_IRELATIVE 42 -#define R_386_NUM 43 - - - - - -#define STT_SPARC_REGISTER 13 - - - -#define EF_SPARCV9_MM 3 -#define EF_SPARCV9_TSO 0 -#define EF_SPARCV9_PSO 1 -#define EF_SPARCV9_RMO 2 -#define EF_SPARC_LEDATA 0x800000 -#define EF_SPARC_EXT_MASK 0xFFFF00 -#define EF_SPARC_32PLUS 0x000100 -#define EF_SPARC_SUN_US1 0x000200 -#define EF_SPARC_HAL_R1 0x000400 -#define EF_SPARC_SUN_US3 0x000800 - - - -#define R_SPARC_NONE 0 -#define R_SPARC_8 1 -#define R_SPARC_16 2 -#define R_SPARC_32 3 -#define R_SPARC_DISP8 4 -#define R_SPARC_DISP16 5 -#define R_SPARC_DISP32 6 -#define R_SPARC_WDISP30 7 -#define R_SPARC_WDISP22 8 -#define R_SPARC_HI22 9 -#define R_SPARC_22 10 -#define R_SPARC_13 11 -#define R_SPARC_LO10 12 -#define R_SPARC_GOT10 13 -#define R_SPARC_GOT13 14 -#define R_SPARC_GOT22 15 -#define R_SPARC_PC10 16 -#define R_SPARC_PC22 17 -#define R_SPARC_WPLT30 18 -#define R_SPARC_COPY 19 -#define R_SPARC_GLOB_DAT 20 -#define R_SPARC_JMP_SLOT 21 -#define R_SPARC_RELATIVE 22 -#define R_SPARC_UA32 23 - - - -#define R_SPARC_PLT32 24 -#define R_SPARC_HIPLT22 25 -#define R_SPARC_LOPLT10 26 -#define R_SPARC_PCPLT32 27 -#define R_SPARC_PCPLT22 28 -#define R_SPARC_PCPLT10 29 -#define R_SPARC_10 30 -#define R_SPARC_11 31 -#define R_SPARC_64 32 -#define R_SPARC_OLO10 33 -#define R_SPARC_HH22 34 -#define R_SPARC_HM10 35 -#define R_SPARC_LM22 36 -#define R_SPARC_PC_HH22 37 -#define R_SPARC_PC_HM10 38 -#define R_SPARC_PC_LM22 39 -#define R_SPARC_WDISP16 40 -#define R_SPARC_WDISP19 41 -#define R_SPARC_GLOB_JMP 42 -#define R_SPARC_7 43 -#define R_SPARC_5 44 -#define R_SPARC_6 45 -#define R_SPARC_DISP64 46 -#define R_SPARC_PLT64 47 -#define R_SPARC_HIX22 48 -#define R_SPARC_LOX10 49 -#define R_SPARC_H44 50 -#define R_SPARC_M44 51 -#define R_SPARC_L44 52 -#define R_SPARC_REGISTER 53 -#define R_SPARC_UA64 54 -#define R_SPARC_UA16 55 -#define R_SPARC_TLS_GD_HI22 56 -#define R_SPARC_TLS_GD_LO10 57 -#define R_SPARC_TLS_GD_ADD 58 -#define R_SPARC_TLS_GD_CALL 59 -#define R_SPARC_TLS_LDM_HI22 60 -#define R_SPARC_TLS_LDM_LO10 61 -#define R_SPARC_TLS_LDM_ADD 62 -#define R_SPARC_TLS_LDM_CALL 63 -#define R_SPARC_TLS_LDO_HIX22 64 -#define R_SPARC_TLS_LDO_LOX10 65 -#define R_SPARC_TLS_LDO_ADD 66 -#define R_SPARC_TLS_IE_HI22 67 -#define R_SPARC_TLS_IE_LO10 68 -#define R_SPARC_TLS_IE_LD 69 -#define R_SPARC_TLS_IE_LDX 70 -#define R_SPARC_TLS_IE_ADD 71 -#define R_SPARC_TLS_LE_HIX22 72 -#define R_SPARC_TLS_LE_LOX10 73 -#define R_SPARC_TLS_DTPMOD32 74 -#define R_SPARC_TLS_DTPMOD64 75 -#define R_SPARC_TLS_DTPOFF32 76 -#define R_SPARC_TLS_DTPOFF64 77 -#define R_SPARC_TLS_TPOFF32 78 -#define R_SPARC_TLS_TPOFF64 79 -#define R_SPARC_GOTDATA_HIX22 80 -#define R_SPARC_GOTDATA_LOX10 81 -#define R_SPARC_GOTDATA_OP_HIX22 82 -#define R_SPARC_GOTDATA_OP_LOX10 83 -#define R_SPARC_GOTDATA_OP 84 -#define R_SPARC_H34 85 -#define R_SPARC_SIZE32 86 -#define R_SPARC_SIZE64 87 -#define R_SPARC_GNU_VTINHERIT 250 -#define R_SPARC_GNU_VTENTRY 251 -#define R_SPARC_REV32 252 - -#define R_SPARC_NUM 253 - - - -#define DT_SPARC_REGISTER 0x70000001 -#define DT_SPARC_NUM 2 - - -#define EF_MIPS_NOREORDER 1 -#define EF_MIPS_PIC 2 -#define EF_MIPS_CPIC 4 -#define EF_MIPS_XGOT 8 -#define EF_MIPS_64BIT_WHIRL 16 -#define EF_MIPS_ABI2 32 -#define EF_MIPS_ABI_ON32 64 -#define EF_MIPS_NAN2008 1024 -#define EF_MIPS_ARCH 0xf0000000 - - - -#define EF_MIPS_ARCH_1 0x00000000 -#define EF_MIPS_ARCH_2 0x10000000 -#define EF_MIPS_ARCH_3 0x20000000 -#define EF_MIPS_ARCH_4 0x30000000 -#define EF_MIPS_ARCH_5 0x40000000 -#define EF_MIPS_ARCH_32 0x50000000 -#define EF_MIPS_ARCH_64 0x60000000 -#define EF_MIPS_ARCH_32R2 0x70000000 -#define EF_MIPS_ARCH_64R2 0x80000000 - - -#define E_MIPS_ARCH_1 0x00000000 -#define E_MIPS_ARCH_2 0x10000000 -#define E_MIPS_ARCH_3 0x20000000 -#define E_MIPS_ARCH_4 0x30000000 -#define E_MIPS_ARCH_5 0x40000000 -#define E_MIPS_ARCH_32 0x50000000 -#define E_MIPS_ARCH_64 0x60000000 - - - -#define SHN_MIPS_ACOMMON 0xff00 -#define SHN_MIPS_TEXT 0xff01 -#define SHN_MIPS_DATA 0xff02 -#define SHN_MIPS_SCOMMON 0xff03 -#define SHN_MIPS_SUNDEFINED 0xff04 - - - -#define SHT_MIPS_LIBLIST 0x70000000 -#define SHT_MIPS_MSYM 0x70000001 -#define SHT_MIPS_CONFLICT 0x70000002 -#define SHT_MIPS_GPTAB 0x70000003 -#define SHT_MIPS_UCODE 0x70000004 -#define SHT_MIPS_DEBUG 0x70000005 -#define SHT_MIPS_REGINFO 0x70000006 -#define SHT_MIPS_PACKAGE 0x70000007 -#define SHT_MIPS_PACKSYM 0x70000008 -#define SHT_MIPS_RELD 0x70000009 -#define SHT_MIPS_IFACE 0x7000000b -#define SHT_MIPS_CONTENT 0x7000000c -#define SHT_MIPS_OPTIONS 0x7000000d -#define SHT_MIPS_SHDR 0x70000010 -#define SHT_MIPS_FDESC 0x70000011 -#define SHT_MIPS_EXTSYM 0x70000012 -#define SHT_MIPS_DENSE 0x70000013 -#define SHT_MIPS_PDESC 0x70000014 -#define SHT_MIPS_LOCSYM 0x70000015 -#define SHT_MIPS_AUXSYM 0x70000016 -#define SHT_MIPS_OPTSYM 0x70000017 -#define SHT_MIPS_LOCSTR 0x70000018 -#define SHT_MIPS_LINE 0x70000019 -#define SHT_MIPS_RFDESC 0x7000001a -#define SHT_MIPS_DELTASYM 0x7000001b -#define SHT_MIPS_DELTAINST 0x7000001c -#define SHT_MIPS_DELTACLASS 0x7000001d -#define SHT_MIPS_DWARF 0x7000001e -#define SHT_MIPS_DELTADECL 0x7000001f -#define SHT_MIPS_SYMBOL_LIB 0x70000020 -#define SHT_MIPS_EVENTS 0x70000021 -#define SHT_MIPS_TRANSLATE 0x70000022 -#define SHT_MIPS_PIXIE 0x70000023 -#define SHT_MIPS_XLATE 0x70000024 -#define SHT_MIPS_XLATE_DEBUG 0x70000025 -#define SHT_MIPS_WHIRL 0x70000026 -#define SHT_MIPS_EH_REGION 0x70000027 -#define SHT_MIPS_XLATE_OLD 0x70000028 -#define SHT_MIPS_PDR_EXCEPTION 0x70000029 - - - -#define SHF_MIPS_GPREL 0x10000000 -#define SHF_MIPS_MERGE 0x20000000 -#define SHF_MIPS_ADDR 0x40000000 -#define SHF_MIPS_STRINGS 0x80000000 -#define SHF_MIPS_NOSTRIP 0x08000000 -#define SHF_MIPS_LOCAL 0x04000000 -#define SHF_MIPS_NAMES 0x02000000 -#define SHF_MIPS_NODUPE 0x01000000 - - - - - -#define STO_MIPS_DEFAULT 0x0 -#define STO_MIPS_INTERNAL 0x1 -#define STO_MIPS_HIDDEN 0x2 -#define STO_MIPS_PROTECTED 0x3 -#define STO_MIPS_PLT 0x8 -#define STO_MIPS_SC_ALIGN_UNUSED 0xff - - -#define STB_MIPS_SPLIT_COMMON 13 - - - -typedef union { - struct { - Elf32_Word gt_current_g_value; - Elf32_Word gt_unused; - } gt_header; - struct { - Elf32_Word gt_g_value; - Elf32_Word gt_bytes; - } gt_entry; -} Elf32_gptab; - - - -typedef struct { - Elf32_Word ri_gprmask; - Elf32_Word ri_cprmask[4]; - Elf32_Sword ri_gp_value; -} Elf32_RegInfo; - - - -typedef struct { - unsigned char kind; - - unsigned char size; - Elf32_Section section; - - Elf32_Word info; -} Elf_Options; - - - -#define ODK_NULL 0 -#define ODK_REGINFO 1 -#define ODK_EXCEPTIONS 2 -#define ODK_PAD 3 -#define ODK_HWPATCH 4 -#define ODK_FILL 5 -#define ODK_TAGS 6 -#define ODK_HWAND 7 -#define ODK_HWOR 8 - - - -#define OEX_FPU_MIN 0x1f -#define OEX_FPU_MAX 0x1f00 -#define OEX_PAGE0 0x10000 -#define OEX_SMM 0x20000 -#define OEX_FPDBUG 0x40000 -#define OEX_PRECISEFP OEX_FPDBUG -#define OEX_DISMISS 0x80000 - -#define OEX_FPU_INVAL 0x10 -#define OEX_FPU_DIV0 0x08 -#define OEX_FPU_OFLO 0x04 -#define OEX_FPU_UFLO 0x02 -#define OEX_FPU_INEX 0x01 - - - -#define OHW_R4KEOP 0x1 -#define OHW_R8KPFETCH 0x2 -#define OHW_R5KEOP 0x4 -#define OHW_R5KCVTL 0x8 - -#define OPAD_PREFIX 0x1 -#define OPAD_POSTFIX 0x2 -#define OPAD_SYMBOL 0x4 - - - -typedef struct { - Elf32_Word hwp_flags1; - Elf32_Word hwp_flags2; -} Elf_Options_Hw; - - - -#define OHWA0_R4KEOP_CHECKED 0x00000001 -#define OHWA1_R4KEOP_CLEAN 0x00000002 - - - -#define R_MIPS_NONE 0 -#define R_MIPS_16 1 -#define R_MIPS_32 2 -#define R_MIPS_REL32 3 -#define R_MIPS_26 4 -#define R_MIPS_HI16 5 -#define R_MIPS_LO16 6 -#define R_MIPS_GPREL16 7 -#define R_MIPS_LITERAL 8 -#define R_MIPS_GOT16 9 -#define R_MIPS_PC16 10 -#define R_MIPS_CALL16 11 -#define R_MIPS_GPREL32 12 - -#define R_MIPS_SHIFT5 16 -#define R_MIPS_SHIFT6 17 -#define R_MIPS_64 18 -#define R_MIPS_GOT_DISP 19 -#define R_MIPS_GOT_PAGE 20 -#define R_MIPS_GOT_OFST 21 -#define R_MIPS_GOT_HI16 22 -#define R_MIPS_GOT_LO16 23 -#define R_MIPS_SUB 24 -#define R_MIPS_INSERT_A 25 -#define R_MIPS_INSERT_B 26 -#define R_MIPS_DELETE 27 -#define R_MIPS_HIGHER 28 -#define R_MIPS_HIGHEST 29 -#define R_MIPS_CALL_HI16 30 -#define R_MIPS_CALL_LO16 31 -#define R_MIPS_SCN_DISP 32 -#define R_MIPS_REL16 33 -#define R_MIPS_ADD_IMMEDIATE 34 -#define R_MIPS_PJUMP 35 -#define R_MIPS_RELGOT 36 -#define R_MIPS_JALR 37 -#define R_MIPS_TLS_DTPMOD32 38 -#define R_MIPS_TLS_DTPREL32 39 -#define R_MIPS_TLS_DTPMOD64 40 -#define R_MIPS_TLS_DTPREL64 41 -#define R_MIPS_TLS_GD 42 -#define R_MIPS_TLS_LDM 43 -#define R_MIPS_TLS_DTPREL_HI16 44 -#define R_MIPS_TLS_DTPREL_LO16 45 -#define R_MIPS_TLS_GOTTPREL 46 -#define R_MIPS_TLS_TPREL32 47 -#define R_MIPS_TLS_TPREL64 48 -#define R_MIPS_TLS_TPREL_HI16 49 -#define R_MIPS_TLS_TPREL_LO16 50 -#define R_MIPS_GLOB_DAT 51 -#define R_MIPS_COPY 126 -#define R_MIPS_JUMP_SLOT 127 - -#define R_MIPS_NUM 128 - - - -#define PT_MIPS_REGINFO 0x70000000 -#define PT_MIPS_RTPROC 0x70000001 -#define PT_MIPS_OPTIONS 0x70000002 - - - -#define PF_MIPS_LOCAL 0x10000000 - - - -#define DT_MIPS_RLD_VERSION 0x70000001 -#define DT_MIPS_TIME_STAMP 0x70000002 -#define DT_MIPS_ICHECKSUM 0x70000003 -#define DT_MIPS_IVERSION 0x70000004 -#define DT_MIPS_FLAGS 0x70000005 -#define DT_MIPS_BASE_ADDRESS 0x70000006 -#define DT_MIPS_MSYM 0x70000007 -#define DT_MIPS_CONFLICT 0x70000008 -#define DT_MIPS_LIBLIST 0x70000009 -#define DT_MIPS_LOCAL_GOTNO 0x7000000a -#define DT_MIPS_CONFLICTNO 0x7000000b -#define DT_MIPS_LIBLISTNO 0x70000010 -#define DT_MIPS_SYMTABNO 0x70000011 -#define DT_MIPS_UNREFEXTNO 0x70000012 -#define DT_MIPS_GOTSYM 0x70000013 -#define DT_MIPS_HIPAGENO 0x70000014 -#define DT_MIPS_RLD_MAP 0x70000016 -#define DT_MIPS_DELTA_CLASS 0x70000017 -#define DT_MIPS_DELTA_CLASS_NO 0x70000018 - -#define DT_MIPS_DELTA_INSTANCE 0x70000019 -#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a - -#define DT_MIPS_DELTA_RELOC 0x7000001b -#define DT_MIPS_DELTA_RELOC_NO 0x7000001c - -#define DT_MIPS_DELTA_SYM 0x7000001d - -#define DT_MIPS_DELTA_SYM_NO 0x7000001e - -#define DT_MIPS_DELTA_CLASSSYM 0x70000020 - -#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 - -#define DT_MIPS_CXX_FLAGS 0x70000022 -#define DT_MIPS_PIXIE_INIT 0x70000023 -#define DT_MIPS_SYMBOL_LIB 0x70000024 -#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 -#define DT_MIPS_LOCAL_GOTIDX 0x70000026 -#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 -#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 -#define DT_MIPS_OPTIONS 0x70000029 -#define DT_MIPS_INTERFACE 0x7000002a -#define DT_MIPS_DYNSTR_ALIGN 0x7000002b -#define DT_MIPS_INTERFACE_SIZE 0x7000002c -#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d - -#define DT_MIPS_PERF_SUFFIX 0x7000002e - -#define DT_MIPS_COMPACT_SIZE 0x7000002f -#define DT_MIPS_GP_VALUE 0x70000030 -#define DT_MIPS_AUX_DYNAMIC 0x70000031 - -#define DT_MIPS_PLTGOT 0x70000032 - -#define DT_MIPS_RWPLT 0x70000034 -#define DT_MIPS_NUM 0x35 - - - -#define RHF_NONE 0 -#define RHF_QUICKSTART (1 << 0) -#define RHF_NOTPOT (1 << 1) -#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) -#define RHF_NO_MOVE (1 << 3) -#define RHF_SGI_ONLY (1 << 4) -#define RHF_GUARANTEE_INIT (1 << 5) -#define RHF_DELTA_C_PLUS_PLUS (1 << 6) -#define RHF_GUARANTEE_START_INIT (1 << 7) -#define RHF_PIXIE (1 << 8) -#define RHF_DEFAULT_DELAY_LOAD (1 << 9) -#define RHF_REQUICKSTART (1 << 10) -#define RHF_REQUICKSTARTED (1 << 11) -#define RHF_CORD (1 << 12) -#define RHF_NO_UNRES_UNDEF (1 << 13) -#define RHF_RLD_ORDER_SAFE (1 << 14) - - - -typedef struct -{ - Elf32_Word l_name; - Elf32_Word l_time_stamp; - Elf32_Word l_checksum; - Elf32_Word l_version; - Elf32_Word l_flags; -} Elf32_Lib; - -typedef struct -{ - Elf64_Word l_name; - Elf64_Word l_time_stamp; - Elf64_Word l_checksum; - Elf64_Word l_version; - Elf64_Word l_flags; -} Elf64_Lib; - - - - -#define LL_NONE 0 -#define LL_EXACT_MATCH (1 << 0) -#define LL_IGNORE_INT_VER (1 << 1) -#define LL_REQUIRE_MINOR (1 << 2) -#define LL_EXPORTS (1 << 3) -#define LL_DELAY_LOAD (1 << 4) -#define LL_DELTA (1 << 5) - - - -typedef Elf32_Addr Elf32_Conflict; - - - - - - -#define EF_PARISC_TRAPNIL 0x00010000 -#define EF_PARISC_EXT 0x00020000 -#define EF_PARISC_LSB 0x00040000 -#define EF_PARISC_WIDE 0x00080000 -#define EF_PARISC_NO_KABP 0x00100000 - -#define EF_PARISC_LAZYSWAP 0x00400000 -#define EF_PARISC_ARCH 0x0000ffff - - - -#define EFA_PARISC_1_0 0x020b -#define EFA_PARISC_1_1 0x0210 -#define EFA_PARISC_2_0 0x0214 - - - -#define SHN_PARISC_ANSI_COMMON 0xff00 - -#define SHN_PARISC_HUGE_COMMON 0xff01 - - - -#define SHT_PARISC_EXT 0x70000000 -#define SHT_PARISC_UNWIND 0x70000001 -#define SHT_PARISC_DOC 0x70000002 - - - -#define SHF_PARISC_SHORT 0x20000000 -#define SHF_PARISC_HUGE 0x40000000 -#define SHF_PARISC_SBP 0x80000000 - - - -#define STT_PARISC_MILLICODE 13 - -#define STT_HP_OPAQUE (STT_LOOS + 0x1) -#define STT_HP_STUB (STT_LOOS + 0x2) - - - -#define R_PARISC_NONE 0 -#define R_PARISC_DIR32 1 -#define R_PARISC_DIR21L 2 -#define R_PARISC_DIR17R 3 -#define R_PARISC_DIR17F 4 -#define R_PARISC_DIR14R 6 -#define R_PARISC_PCREL32 9 -#define R_PARISC_PCREL21L 10 -#define R_PARISC_PCREL17R 11 -#define R_PARISC_PCREL17F 12 -#define R_PARISC_PCREL14R 14 -#define R_PARISC_DPREL21L 18 -#define R_PARISC_DPREL14R 22 -#define R_PARISC_GPREL21L 26 -#define R_PARISC_GPREL14R 30 -#define R_PARISC_LTOFF21L 34 -#define R_PARISC_LTOFF14R 38 -#define R_PARISC_SECREL32 41 -#define R_PARISC_SEGBASE 48 -#define R_PARISC_SEGREL32 49 -#define R_PARISC_PLTOFF21L 50 -#define R_PARISC_PLTOFF14R 54 -#define R_PARISC_LTOFF_FPTR32 57 -#define R_PARISC_LTOFF_FPTR21L 58 -#define R_PARISC_LTOFF_FPTR14R 62 -#define R_PARISC_FPTR64 64 -#define R_PARISC_PLABEL32 65 -#define R_PARISC_PLABEL21L 66 -#define R_PARISC_PLABEL14R 70 -#define R_PARISC_PCREL64 72 -#define R_PARISC_PCREL22F 74 -#define R_PARISC_PCREL14WR 75 -#define R_PARISC_PCREL14DR 76 -#define R_PARISC_PCREL16F 77 -#define R_PARISC_PCREL16WF 78 -#define R_PARISC_PCREL16DF 79 -#define R_PARISC_DIR64 80 -#define R_PARISC_DIR14WR 83 -#define R_PARISC_DIR14DR 84 -#define R_PARISC_DIR16F 85 -#define R_PARISC_DIR16WF 86 -#define R_PARISC_DIR16DF 87 -#define R_PARISC_GPREL64 88 -#define R_PARISC_GPREL14WR 91 -#define R_PARISC_GPREL14DR 92 -#define R_PARISC_GPREL16F 93 -#define R_PARISC_GPREL16WF 94 -#define R_PARISC_GPREL16DF 95 -#define R_PARISC_LTOFF64 96 -#define R_PARISC_LTOFF14WR 99 -#define R_PARISC_LTOFF14DR 100 -#define R_PARISC_LTOFF16F 101 -#define R_PARISC_LTOFF16WF 102 -#define R_PARISC_LTOFF16DF 103 -#define R_PARISC_SECREL64 104 -#define R_PARISC_SEGREL64 112 -#define R_PARISC_PLTOFF14WR 115 -#define R_PARISC_PLTOFF14DR 116 -#define R_PARISC_PLTOFF16F 117 -#define R_PARISC_PLTOFF16WF 118 -#define R_PARISC_PLTOFF16DF 119 -#define R_PARISC_LTOFF_FPTR64 120 -#define R_PARISC_LTOFF_FPTR14WR 123 -#define R_PARISC_LTOFF_FPTR14DR 124 -#define R_PARISC_LTOFF_FPTR16F 125 -#define R_PARISC_LTOFF_FPTR16WF 126 -#define R_PARISC_LTOFF_FPTR16DF 127 -#define R_PARISC_LORESERVE 128 -#define R_PARISC_COPY 128 -#define R_PARISC_IPLT 129 -#define R_PARISC_EPLT 130 -#define R_PARISC_TPREL32 153 -#define R_PARISC_TPREL21L 154 -#define R_PARISC_TPREL14R 158 -#define R_PARISC_LTOFF_TP21L 162 -#define R_PARISC_LTOFF_TP14R 166 -#define R_PARISC_LTOFF_TP14F 167 -#define R_PARISC_TPREL64 216 -#define R_PARISC_TPREL14WR 219 -#define R_PARISC_TPREL14DR 220 -#define R_PARISC_TPREL16F 221 -#define R_PARISC_TPREL16WF 222 -#define R_PARISC_TPREL16DF 223 -#define R_PARISC_LTOFF_TP64 224 -#define R_PARISC_LTOFF_TP14WR 227 -#define R_PARISC_LTOFF_TP14DR 228 -#define R_PARISC_LTOFF_TP16F 229 -#define R_PARISC_LTOFF_TP16WF 230 -#define R_PARISC_LTOFF_TP16DF 231 -#define R_PARISC_GNU_VTENTRY 232 -#define R_PARISC_GNU_VTINHERIT 233 -#define R_PARISC_TLS_GD21L 234 -#define R_PARISC_TLS_GD14R 235 -#define R_PARISC_TLS_GDCALL 236 -#define R_PARISC_TLS_LDM21L 237 -#define R_PARISC_TLS_LDM14R 238 -#define R_PARISC_TLS_LDMCALL 239 -#define R_PARISC_TLS_LDO21L 240 -#define R_PARISC_TLS_LDO14R 241 -#define R_PARISC_TLS_DTPMOD32 242 -#define R_PARISC_TLS_DTPMOD64 243 -#define R_PARISC_TLS_DTPOFF32 244 -#define R_PARISC_TLS_DTPOFF64 245 -#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L -#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R -#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L -#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R -#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32 -#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64 -#define R_PARISC_HIRESERVE 255 - - - -#define PT_HP_TLS (PT_LOOS + 0x0) -#define PT_HP_CORE_NONE (PT_LOOS + 0x1) -#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) -#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) -#define PT_HP_CORE_COMM (PT_LOOS + 0x4) -#define PT_HP_CORE_PROC (PT_LOOS + 0x5) -#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) -#define PT_HP_CORE_STACK (PT_LOOS + 0x7) -#define PT_HP_CORE_SHM (PT_LOOS + 0x8) -#define PT_HP_CORE_MMF (PT_LOOS + 0x9) -#define PT_HP_PARALLEL (PT_LOOS + 0x10) -#define PT_HP_FASTBIND (PT_LOOS + 0x11) -#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) -#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) -#define PT_HP_STACK (PT_LOOS + 0x14) - -#define PT_PARISC_ARCHEXT 0x70000000 -#define PT_PARISC_UNWIND 0x70000001 - - - -#define PF_PARISC_SBP 0x08000000 - -#define PF_HP_PAGE_SIZE 0x00100000 -#define PF_HP_FAR_SHARED 0x00200000 -#define PF_HP_NEAR_SHARED 0x00400000 -#define PF_HP_CODE 0x01000000 -#define PF_HP_MODIFY 0x02000000 -#define PF_HP_LAZYSWAP 0x04000000 -#define PF_HP_SBP 0x08000000 - - - - - - -#define EF_ALPHA_32BIT 1 -#define EF_ALPHA_CANRELAX 2 - - - - -#define SHT_ALPHA_DEBUG 0x70000001 -#define SHT_ALPHA_REGINFO 0x70000002 - - - -#define SHF_ALPHA_GPREL 0x10000000 - - -#define STO_ALPHA_NOPV 0x80 -#define STO_ALPHA_STD_GPLOAD 0x88 - - - -#define R_ALPHA_NONE 0 -#define R_ALPHA_REFLONG 1 -#define R_ALPHA_REFQUAD 2 -#define R_ALPHA_GPREL32 3 -#define R_ALPHA_LITERAL 4 -#define R_ALPHA_LITUSE 5 -#define R_ALPHA_GPDISP 6 -#define R_ALPHA_BRADDR 7 -#define R_ALPHA_HINT 8 -#define R_ALPHA_SREL16 9 -#define R_ALPHA_SREL32 10 -#define R_ALPHA_SREL64 11 -#define R_ALPHA_GPRELHIGH 17 -#define R_ALPHA_GPRELLOW 18 -#define R_ALPHA_GPREL16 19 -#define R_ALPHA_COPY 24 -#define R_ALPHA_GLOB_DAT 25 -#define R_ALPHA_JMP_SLOT 26 -#define R_ALPHA_RELATIVE 27 -#define R_ALPHA_TLS_GD_HI 28 -#define R_ALPHA_TLSGD 29 -#define R_ALPHA_TLS_LDM 30 -#define R_ALPHA_DTPMOD64 31 -#define R_ALPHA_GOTDTPREL 32 -#define R_ALPHA_DTPREL64 33 -#define R_ALPHA_DTPRELHI 34 -#define R_ALPHA_DTPRELLO 35 -#define R_ALPHA_DTPREL16 36 -#define R_ALPHA_GOTTPREL 37 -#define R_ALPHA_TPREL64 38 -#define R_ALPHA_TPRELHI 39 -#define R_ALPHA_TPRELLO 40 -#define R_ALPHA_TPREL16 41 - -#define R_ALPHA_NUM 46 - - -#define LITUSE_ALPHA_ADDR 0 -#define LITUSE_ALPHA_BASE 1 -#define LITUSE_ALPHA_BYTOFF 2 -#define LITUSE_ALPHA_JSR 3 -#define LITUSE_ALPHA_TLS_GD 4 -#define LITUSE_ALPHA_TLS_LDM 5 - - -#define DT_ALPHA_PLTRO (DT_LOPROC + 0) -#define DT_ALPHA_NUM 1 - - - - -#define EF_PPC_EMB 0x80000000 - - -#define EF_PPC_RELOCATABLE 0x00010000 -#define EF_PPC_RELOCATABLE_LIB 0x00008000 - - - -#define R_PPC_NONE 0 -#define R_PPC_ADDR32 1 -#define R_PPC_ADDR24 2 -#define R_PPC_ADDR16 3 -#define R_PPC_ADDR16_LO 4 -#define R_PPC_ADDR16_HI 5 -#define R_PPC_ADDR16_HA 6 -#define R_PPC_ADDR14 7 -#define R_PPC_ADDR14_BRTAKEN 8 -#define R_PPC_ADDR14_BRNTAKEN 9 -#define R_PPC_REL24 10 -#define R_PPC_REL14 11 -#define R_PPC_REL14_BRTAKEN 12 -#define R_PPC_REL14_BRNTAKEN 13 -#define R_PPC_GOT16 14 -#define R_PPC_GOT16_LO 15 -#define R_PPC_GOT16_HI 16 -#define R_PPC_GOT16_HA 17 -#define R_PPC_PLTREL24 18 -#define R_PPC_COPY 19 -#define R_PPC_GLOB_DAT 20 -#define R_PPC_JMP_SLOT 21 -#define R_PPC_RELATIVE 22 -#define R_PPC_LOCAL24PC 23 -#define R_PPC_UADDR32 24 -#define R_PPC_UADDR16 25 -#define R_PPC_REL32 26 -#define R_PPC_PLT32 27 -#define R_PPC_PLTREL32 28 -#define R_PPC_PLT16_LO 29 -#define R_PPC_PLT16_HI 30 -#define R_PPC_PLT16_HA 31 -#define R_PPC_SDAREL16 32 -#define R_PPC_SECTOFF 33 -#define R_PPC_SECTOFF_LO 34 -#define R_PPC_SECTOFF_HI 35 -#define R_PPC_SECTOFF_HA 36 - - -#define R_PPC_TLS 67 -#define R_PPC_DTPMOD32 68 -#define R_PPC_TPREL16 69 -#define R_PPC_TPREL16_LO 70 -#define R_PPC_TPREL16_HI 71 -#define R_PPC_TPREL16_HA 72 -#define R_PPC_TPREL32 73 -#define R_PPC_DTPREL16 74 -#define R_PPC_DTPREL16_LO 75 -#define R_PPC_DTPREL16_HI 76 -#define R_PPC_DTPREL16_HA 77 -#define R_PPC_DTPREL32 78 -#define R_PPC_GOT_TLSGD16 79 -#define R_PPC_GOT_TLSGD16_LO 80 -#define R_PPC_GOT_TLSGD16_HI 81 -#define R_PPC_GOT_TLSGD16_HA 82 -#define R_PPC_GOT_TLSLD16 83 -#define R_PPC_GOT_TLSLD16_LO 84 -#define R_PPC_GOT_TLSLD16_HI 85 -#define R_PPC_GOT_TLSLD16_HA 86 -#define R_PPC_GOT_TPREL16 87 -#define R_PPC_GOT_TPREL16_LO 88 -#define R_PPC_GOT_TPREL16_HI 89 -#define R_PPC_GOT_TPREL16_HA 90 -#define R_PPC_GOT_DTPREL16 91 -#define R_PPC_GOT_DTPREL16_LO 92 -#define R_PPC_GOT_DTPREL16_HI 93 -#define R_PPC_GOT_DTPREL16_HA 94 - - - -#define R_PPC_EMB_NADDR32 101 -#define R_PPC_EMB_NADDR16 102 -#define R_PPC_EMB_NADDR16_LO 103 -#define R_PPC_EMB_NADDR16_HI 104 -#define R_PPC_EMB_NADDR16_HA 105 -#define R_PPC_EMB_SDAI16 106 -#define R_PPC_EMB_SDA2I16 107 -#define R_PPC_EMB_SDA2REL 108 -#define R_PPC_EMB_SDA21 109 -#define R_PPC_EMB_MRKREF 110 -#define R_PPC_EMB_RELSEC16 111 -#define R_PPC_EMB_RELST_LO 112 -#define R_PPC_EMB_RELST_HI 113 -#define R_PPC_EMB_RELST_HA 114 -#define R_PPC_EMB_BIT_FLD 115 -#define R_PPC_EMB_RELSDA 116 - - -#define R_PPC_DIAB_SDA21_LO 180 -#define R_PPC_DIAB_SDA21_HI 181 -#define R_PPC_DIAB_SDA21_HA 182 -#define R_PPC_DIAB_RELSDA_LO 183 -#define R_PPC_DIAB_RELSDA_HI 184 -#define R_PPC_DIAB_RELSDA_HA 185 - - -#define R_PPC_IRELATIVE 248 - - -#define R_PPC_REL16 249 -#define R_PPC_REL16_LO 250 -#define R_PPC_REL16_HI 251 -#define R_PPC_REL16_HA 252 - - - -#define R_PPC_TOC16 255 - - -#define DT_PPC_GOT (DT_LOPROC + 0) -#define DT_PPC_NUM 1 - - -#define R_PPC64_NONE R_PPC_NONE -#define R_PPC64_ADDR32 R_PPC_ADDR32 -#define R_PPC64_ADDR24 R_PPC_ADDR24 -#define R_PPC64_ADDR16 R_PPC_ADDR16 -#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO -#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI -#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA -#define R_PPC64_ADDR14 R_PPC_ADDR14 -#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN -#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN -#define R_PPC64_REL24 R_PPC_REL24 -#define R_PPC64_REL14 R_PPC_REL14 -#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN -#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN -#define R_PPC64_GOT16 R_PPC_GOT16 -#define R_PPC64_GOT16_LO R_PPC_GOT16_LO -#define R_PPC64_GOT16_HI R_PPC_GOT16_HI -#define R_PPC64_GOT16_HA R_PPC_GOT16_HA - -#define R_PPC64_COPY R_PPC_COPY -#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT -#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT -#define R_PPC64_RELATIVE R_PPC_RELATIVE - -#define R_PPC64_UADDR32 R_PPC_UADDR32 -#define R_PPC64_UADDR16 R_PPC_UADDR16 -#define R_PPC64_REL32 R_PPC_REL32 -#define R_PPC64_PLT32 R_PPC_PLT32 -#define R_PPC64_PLTREL32 R_PPC_PLTREL32 -#define R_PPC64_PLT16_LO R_PPC_PLT16_LO -#define R_PPC64_PLT16_HI R_PPC_PLT16_HI -#define R_PPC64_PLT16_HA R_PPC_PLT16_HA - -#define R_PPC64_SECTOFF R_PPC_SECTOFF -#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO -#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI -#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA -#define R_PPC64_ADDR30 37 -#define R_PPC64_ADDR64 38 -#define R_PPC64_ADDR16_HIGHER 39 -#define R_PPC64_ADDR16_HIGHERA 40 -#define R_PPC64_ADDR16_HIGHEST 41 -#define R_PPC64_ADDR16_HIGHESTA 42 -#define R_PPC64_UADDR64 43 -#define R_PPC64_REL64 44 -#define R_PPC64_PLT64 45 -#define R_PPC64_PLTREL64 46 -#define R_PPC64_TOC16 47 -#define R_PPC64_TOC16_LO 48 -#define R_PPC64_TOC16_HI 49 -#define R_PPC64_TOC16_HA 50 -#define R_PPC64_TOC 51 -#define R_PPC64_PLTGOT16 52 -#define R_PPC64_PLTGOT16_LO 53 -#define R_PPC64_PLTGOT16_HI 54 -#define R_PPC64_PLTGOT16_HA 55 - -#define R_PPC64_ADDR16_DS 56 -#define R_PPC64_ADDR16_LO_DS 57 -#define R_PPC64_GOT16_DS 58 -#define R_PPC64_GOT16_LO_DS 59 -#define R_PPC64_PLT16_LO_DS 60 -#define R_PPC64_SECTOFF_DS 61 -#define R_PPC64_SECTOFF_LO_DS 62 -#define R_PPC64_TOC16_DS 63 -#define R_PPC64_TOC16_LO_DS 64 -#define R_PPC64_PLTGOT16_DS 65 -#define R_PPC64_PLTGOT16_LO_DS 66 - - -#define R_PPC64_TLS 67 -#define R_PPC64_DTPMOD64 68 -#define R_PPC64_TPREL16 69 -#define R_PPC64_TPREL16_LO 70 -#define R_PPC64_TPREL16_HI 71 -#define R_PPC64_TPREL16_HA 72 -#define R_PPC64_TPREL64 73 -#define R_PPC64_DTPREL16 74 -#define R_PPC64_DTPREL16_LO 75 -#define R_PPC64_DTPREL16_HI 76 -#define R_PPC64_DTPREL16_HA 77 -#define R_PPC64_DTPREL64 78 -#define R_PPC64_GOT_TLSGD16 79 -#define R_PPC64_GOT_TLSGD16_LO 80 -#define R_PPC64_GOT_TLSGD16_HI 81 -#define R_PPC64_GOT_TLSGD16_HA 82 -#define R_PPC64_GOT_TLSLD16 83 -#define R_PPC64_GOT_TLSLD16_LO 84 -#define R_PPC64_GOT_TLSLD16_HI 85 -#define R_PPC64_GOT_TLSLD16_HA 86 -#define R_PPC64_GOT_TPREL16_DS 87 -#define R_PPC64_GOT_TPREL16_LO_DS 88 -#define R_PPC64_GOT_TPREL16_HI 89 -#define R_PPC64_GOT_TPREL16_HA 90 -#define R_PPC64_GOT_DTPREL16_DS 91 -#define R_PPC64_GOT_DTPREL16_LO_DS 92 -#define R_PPC64_GOT_DTPREL16_HI 93 -#define R_PPC64_GOT_DTPREL16_HA 94 -#define R_PPC64_TPREL16_DS 95 -#define R_PPC64_TPREL16_LO_DS 96 -#define R_PPC64_TPREL16_HIGHER 97 -#define R_PPC64_TPREL16_HIGHERA 98 -#define R_PPC64_TPREL16_HIGHEST 99 -#define R_PPC64_TPREL16_HIGHESTA 100 -#define R_PPC64_DTPREL16_DS 101 -#define R_PPC64_DTPREL16_LO_DS 102 -#define R_PPC64_DTPREL16_HIGHER 103 -#define R_PPC64_DTPREL16_HIGHERA 104 -#define R_PPC64_DTPREL16_HIGHEST 105 -#define R_PPC64_DTPREL16_HIGHESTA 106 - - -#define R_PPC64_JMP_IREL 247 -#define R_PPC64_IRELATIVE 248 -#define R_PPC64_REL16 249 -#define R_PPC64_REL16_LO 250 -#define R_PPC64_REL16_HI 251 -#define R_PPC64_REL16_HA 252 - - -#define DT_PPC64_GLINK (DT_LOPROC + 0) -#define DT_PPC64_OPD (DT_LOPROC + 1) -#define DT_PPC64_OPDSZ (DT_LOPROC + 2) -#define DT_PPC64_NUM 3 - - - - - -#define EF_ARM_RELEXEC 0x01 -#define EF_ARM_HASENTRY 0x02 -#define EF_ARM_INTERWORK 0x04 -#define EF_ARM_APCS_26 0x08 -#define EF_ARM_APCS_FLOAT 0x10 -#define EF_ARM_PIC 0x20 -#define EF_ARM_ALIGN8 0x40 -#define EF_ARM_NEW_ABI 0x80 -#define EF_ARM_OLD_ABI 0x100 -#define EF_ARM_SOFT_FLOAT 0x200 -#define EF_ARM_VFP_FLOAT 0x400 -#define EF_ARM_MAVERICK_FLOAT 0x800 - -#define EF_ARM_ABI_FLOAT_SOFT 0x200 -#define EF_ARM_ABI_FLOAT_HARD 0x400 - - -#define EF_ARM_SYMSARESORTED 0x04 -#define EF_ARM_DYNSYMSUSESEGIDX 0x08 -#define EF_ARM_MAPSYMSFIRST 0x10 -#define EF_ARM_EABIMASK 0XFF000000 - - -#define EF_ARM_BE8 0x00800000 -#define EF_ARM_LE8 0x00400000 - -#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) -#define EF_ARM_EABI_UNKNOWN 0x00000000 -#define EF_ARM_EABI_VER1 0x01000000 -#define EF_ARM_EABI_VER2 0x02000000 -#define EF_ARM_EABI_VER3 0x03000000 -#define EF_ARM_EABI_VER4 0x04000000 -#define EF_ARM_EABI_VER5 0x05000000 - - -#define STT_ARM_TFUNC STT_LOPROC -#define STT_ARM_16BIT STT_HIPROC - - -#define SHF_ARM_ENTRYSECT 0x10000000 -#define SHF_ARM_COMDEF 0x80000000 - - - -#define PF_ARM_SB 0x10000000 - -#define PF_ARM_PI 0x20000000 -#define PF_ARM_ABS 0x40000000 - - -#define PT_ARM_EXIDX (PT_LOPROC + 1) - - -#define SHT_ARM_EXIDX (SHT_LOPROC + 1) -#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) -#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) - - -#define R_AARCH64_NONE 0 -#define R_AARCH64_ABS64 257 -#define R_AARCH64_ABS32 258 -#define R_AARCH64_ABS16 259 -#define R_AARCH64_PREL64 260 -#define R_AARCH64_PREL32 261 -#define R_AARCH64_PREL16 262 -#define R_AARCH64_MOVW_UABS_G0 263 -#define R_AARCH64_MOVW_UABS_G0_NC 264 -#define R_AARCH64_MOVW_UABS_G1 265 -#define R_AARCH64_MOVW_UABS_G1_NC 266 -#define R_AARCH64_MOVW_UABS_G2 267 -#define R_AARCH64_MOVW_UABS_G2_NC 268 -#define R_AARCH64_MOVW_UABS_G3 269 -#define R_AARCH64_MOVW_SABS_G0 270 -#define R_AARCH64_MOVW_SABS_G1 271 -#define R_AARCH64_MOVW_SABS_G2 272 -#define R_AARCH64_LD_PREL_LO19 273 -#define R_AARCH64_ADR_PREL_LO21 274 -#define R_AARCH64_ADR_PREL_PG_HI21 275 -#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 -#define R_AARCH64_ADD_ABS_LO12_NC 277 -#define R_AARCH64_LDST8_ABS_LO12_NC 278 -#define R_AARCH64_TSTBR14 279 -#define R_AARCH64_CONDBR19 280 -#define R_AARCH64_JUMP26 282 -#define R_AARCH64_CALL26 283 -#define R_AARCH64_LDST16_ABS_LO12_NC 284 -#define R_AARCH64_LDST32_ABS_LO12_NC 285 -#define R_AARCH64_LDST64_ABS_LO12_NC 286 -#define R_AARCH64_MOVW_PREL_G0 287 -#define R_AARCH64_MOVW_PREL_G0_NC 288 -#define R_AARCH64_MOVW_PREL_G1 289 -#define R_AARCH64_MOVW_PREL_G1_NC 290 -#define R_AARCH64_MOVW_PREL_G2 291 -#define R_AARCH64_MOVW_PREL_G2_NC 292 -#define R_AARCH64_MOVW_PREL_G3 293 -#define R_AARCH64_LDST128_ABS_LO12_NC 299 -#define R_AARCH64_MOVW_GOTOFF_G0 300 -#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 -#define R_AARCH64_MOVW_GOTOFF_G1 302 -#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 -#define R_AARCH64_MOVW_GOTOFF_G2 304 -#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 -#define R_AARCH64_MOVW_GOTOFF_G3 306 -#define R_AARCH64_GOTREL64 307 -#define R_AARCH64_GOTREL32 308 -#define R_AARCH64_GOT_LD_PREL19 309 -#define R_AARCH64_LD64_GOTOFF_LO15 310 -#define R_AARCH64_ADR_GOT_PAGE 311 -#define R_AARCH64_LD64_GOT_LO12_NC 312 -#define R_AARCH64_LD64_GOTPAGE_LO15 313 -#define R_AARCH64_TLSGD_ADR_PREL21 512 -#define R_AARCH64_TLSGD_ADR_PAGE21 513 -#define R_AARCH64_TLSGD_ADD_LO12_NC 514 -#define R_AARCH64_TLSGD_MOVW_G1 515 -#define R_AARCH64_TLSGD_MOVW_G0_NC 516 -#define R_AARCH64_TLSLD_ADR_PREL21 517 -#define R_AARCH64_TLSLD_ADR_PAGE21 518 -#define R_AARCH64_TLSLD_ADD_LO12_NC 519 -#define R_AARCH64_TLSLD_MOVW_G1 520 -#define R_AARCH64_TLSLD_MOVW_G0_NC 521 -#define R_AARCH64_TLSLD_LD_PREL19 522 -#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 -#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 -#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 -#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 -#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 -#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 -#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 -#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 -#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 -#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 -#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 -#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 -#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 -#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 -#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 -#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 -#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 -#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 -#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 -#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 -#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 -#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 -#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 -#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 -#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 -#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 -#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 -#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 -#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 -#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 -#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 -#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 -#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 -#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 -#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 -#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 -#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 -#define R_AARCH64_TLSDESC_LD_PREL19 560 -#define R_AARCH64_TLSDESC_ADR_PREL21 561 -#define R_AARCH64_TLSDESC_ADR_PAGE21 562 -#define R_AARCH64_TLSDESC_LD64_LO12 563 -#define R_AARCH64_TLSDESC_ADD_LO12 564 -#define R_AARCH64_TLSDESC_OFF_G1 565 -#define R_AARCH64_TLSDESC_OFF_G0_NC 566 -#define R_AARCH64_TLSDESC_LDR 567 -#define R_AARCH64_TLSDESC_ADD 568 -#define R_AARCH64_TLSDESC_CALL 569 -#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 -#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 -#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 -#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 -#define R_AARCH64_COPY 1024 -#define R_AARCH64_GLOB_DAT 1025 -#define R_AARCH64_JUMP_SLOT 1026 -#define R_AARCH64_RELATIVE 1027 -#define R_AARCH64_TLS_DTPMOD64 1028 -#define R_AARCH64_TLS_DTPREL64 1029 -#define R_AARCH64_TLS_TPREL64 1030 -#define R_AARCH64_TLSDESC 1031 - - -#define R_ARM_NONE 0 -#define R_ARM_PC24 1 -#define R_ARM_ABS32 2 -#define R_ARM_REL32 3 -#define R_ARM_PC13 4 -#define R_ARM_ABS16 5 -#define R_ARM_ABS12 6 -#define R_ARM_THM_ABS5 7 -#define R_ARM_ABS8 8 -#define R_ARM_SBREL32 9 -#define R_ARM_THM_PC22 10 -#define R_ARM_THM_PC8 11 -#define R_ARM_AMP_VCALL9 12 -#define R_ARM_TLS_DESC 13 -#define R_ARM_THM_SWI8 14 -#define R_ARM_XPC25 15 -#define R_ARM_THM_XPC22 16 -#define R_ARM_TLS_DTPMOD32 17 -#define R_ARM_TLS_DTPOFF32 18 -#define R_ARM_TLS_TPOFF32 19 -#define R_ARM_COPY 20 -#define R_ARM_GLOB_DAT 21 -#define R_ARM_JUMP_SLOT 22 -#define R_ARM_RELATIVE 23 -#define R_ARM_GOTOFF 24 -#define R_ARM_GOTPC 25 -#define R_ARM_GOT32 26 -#define R_ARM_PLT32 27 -#define R_ARM_CALL 28 -#define R_ARM_JUMP24 29 -#define R_ARM_THM_JUMP24 30 -#define R_ARM_BASE_ABS 31 -#define R_ARM_ALU_PCREL_7_0 32 -#define R_ARM_ALU_PCREL_15_8 33 -#define R_ARM_ALU_PCREL_23_15 34 -#define R_ARM_LDR_SBREL_11_0 35 -#define R_ARM_ALU_SBREL_19_12 36 -#define R_ARM_ALU_SBREL_27_20 37 -#define R_ARM_TARGET1 38 -#define R_ARM_SBREL31 39 -#define R_ARM_V4BX 40 -#define R_ARM_TARGET2 41 -#define R_ARM_PREL31 42 -#define R_ARM_MOVW_ABS_NC 43 -#define R_ARM_MOVT_ABS 44 -#define R_ARM_MOVW_PREL_NC 45 -#define R_ARM_MOVT_PREL 46 -#define R_ARM_THM_MOVW_ABS_NC 47 -#define R_ARM_THM_MOVT_ABS 48 -#define R_ARM_THM_MOVW_PREL_NC 49 -#define R_ARM_THM_MOVT_PREL 50 -#define R_ARM_THM_JUMP19 51 -#define R_ARM_THM_JUMP6 52 -#define R_ARM_THM_ALU_PREL_11_0 53 -#define R_ARM_THM_PC12 54 -#define R_ARM_ABS32_NOI 55 -#define R_ARM_REL32_NOI 56 -#define R_ARM_ALU_PC_G0_NC 57 -#define R_ARM_ALU_PC_G0 58 -#define R_ARM_ALU_PC_G1_NC 59 -#define R_ARM_ALU_PC_G1 60 -#define R_ARM_ALU_PC_G2 61 -#define R_ARM_LDR_PC_G1 62 -#define R_ARM_LDR_PC_G2 63 -#define R_ARM_LDRS_PC_G0 64 -#define R_ARM_LDRS_PC_G1 65 -#define R_ARM_LDRS_PC_G2 66 -#define R_ARM_LDC_PC_G0 67 -#define R_ARM_LDC_PC_G1 68 -#define R_ARM_LDC_PC_G2 69 -#define R_ARM_ALU_SB_G0_NC 70 -#define R_ARM_ALU_SB_G0 71 -#define R_ARM_ALU_SB_G1_NC 72 -#define R_ARM_ALU_SB_G1 73 -#define R_ARM_ALU_SB_G2 74 -#define R_ARM_LDR_SB_G0 75 -#define R_ARM_LDR_SB_G1 76 -#define R_ARM_LDR_SB_G2 77 -#define R_ARM_LDRS_SB_G0 78 -#define R_ARM_LDRS_SB_G1 79 -#define R_ARM_LDRS_SB_G2 80 -#define R_ARM_LDC_SB_G0 81 -#define R_ARM_LDC_SB_G1 82 -#define R_ARM_LDC_SB_G2 83 -#define R_ARM_MOVW_BREL_NC 84 -#define R_ARM_MOVT_BREL 85 -#define R_ARM_MOVW_BREL 86 -#define R_ARM_THM_MOVW_BREL_NC 87 -#define R_ARM_THM_MOVT_BREL 88 -#define R_ARM_THM_MOVW_BREL 89 -#define R_ARM_TLS_GOTDESC 90 -#define R_ARM_TLS_CALL 91 -#define R_ARM_TLS_DESCSEQ 92 -#define R_ARM_THM_TLS_CALL 93 -#define R_ARM_PLT32_ABS 94 -#define R_ARM_GOT_ABS 95 -#define R_ARM_GOT_PREL 96 -#define R_ARM_GOT_BREL12 97 -#define R_ARM_GOTOFF12 98 -#define R_ARM_GOTRELAX 99 -#define R_ARM_GNU_VTENTRY 100 -#define R_ARM_GNU_VTINHERIT 101 -#define R_ARM_THM_PC11 102 -#define R_ARM_THM_PC9 103 -#define R_ARM_TLS_GD32 104 - -#define R_ARM_TLS_LDM32 105 - -#define R_ARM_TLS_LDO32 106 - -#define R_ARM_TLS_IE32 107 - -#define R_ARM_TLS_LE32 108 -#define R_ARM_TLS_LDO12 109 -#define R_ARM_TLS_LE12 110 -#define R_ARM_TLS_IE12GP 111 -#define R_ARM_ME_TOO 128 -#define R_ARM_THM_TLS_DESCSEQ 129 -#define R_ARM_THM_TLS_DESCSEQ16 129 -#define R_ARM_THM_TLS_DESCSEQ32 130 -#define R_ARM_THM_GOT_BREL12 131 -#define R_ARM_IRELATIVE 160 -#define R_ARM_RXPC25 249 -#define R_ARM_RSBREL32 250 -#define R_ARM_THM_RPC22 251 -#define R_ARM_RREL32 252 -#define R_ARM_RABS22 253 -#define R_ARM_RPC24 254 -#define R_ARM_RBASE 255 - -#define R_ARM_NUM 256 - - - - -#define EF_IA_64_MASKOS 0x0000000f -#define EF_IA_64_ABI64 0x00000010 -#define EF_IA_64_ARCH 0xff000000 - - -#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) -#define PT_IA_64_UNWIND (PT_LOPROC + 1) -#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) -#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) -#define PT_IA_64_HP_STACK (PT_LOOS + 0x14) - - -#define PF_IA_64_NORECOV 0x80000000 - - -#define SHT_IA_64_EXT (SHT_LOPROC + 0) -#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) - - -#define SHF_IA_64_SHORT 0x10000000 -#define SHF_IA_64_NORECOV 0x20000000 - - -#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) -#define DT_IA_64_NUM 1 - - -#define R_IA64_NONE 0x00 -#define R_IA64_IMM14 0x21 -#define R_IA64_IMM22 0x22 -#define R_IA64_IMM64 0x23 -#define R_IA64_DIR32MSB 0x24 -#define R_IA64_DIR32LSB 0x25 -#define R_IA64_DIR64MSB 0x26 -#define R_IA64_DIR64LSB 0x27 -#define R_IA64_GPREL22 0x2a -#define R_IA64_GPREL64I 0x2b -#define R_IA64_GPREL32MSB 0x2c -#define R_IA64_GPREL32LSB 0x2d -#define R_IA64_GPREL64MSB 0x2e -#define R_IA64_GPREL64LSB 0x2f -#define R_IA64_LTOFF22 0x32 -#define R_IA64_LTOFF64I 0x33 -#define R_IA64_PLTOFF22 0x3a -#define R_IA64_PLTOFF64I 0x3b -#define R_IA64_PLTOFF64MSB 0x3e -#define R_IA64_PLTOFF64LSB 0x3f -#define R_IA64_FPTR64I 0x43 -#define R_IA64_FPTR32MSB 0x44 -#define R_IA64_FPTR32LSB 0x45 -#define R_IA64_FPTR64MSB 0x46 -#define R_IA64_FPTR64LSB 0x47 -#define R_IA64_PCREL60B 0x48 -#define R_IA64_PCREL21B 0x49 -#define R_IA64_PCREL21M 0x4a -#define R_IA64_PCREL21F 0x4b -#define R_IA64_PCREL32MSB 0x4c -#define R_IA64_PCREL32LSB 0x4d -#define R_IA64_PCREL64MSB 0x4e -#define R_IA64_PCREL64LSB 0x4f -#define R_IA64_LTOFF_FPTR22 0x52 -#define R_IA64_LTOFF_FPTR64I 0x53 -#define R_IA64_LTOFF_FPTR32MSB 0x54 -#define R_IA64_LTOFF_FPTR32LSB 0x55 -#define R_IA64_LTOFF_FPTR64MSB 0x56 -#define R_IA64_LTOFF_FPTR64LSB 0x57 -#define R_IA64_SEGREL32MSB 0x5c -#define R_IA64_SEGREL32LSB 0x5d -#define R_IA64_SEGREL64MSB 0x5e -#define R_IA64_SEGREL64LSB 0x5f -#define R_IA64_SECREL32MSB 0x64 -#define R_IA64_SECREL32LSB 0x65 -#define R_IA64_SECREL64MSB 0x66 -#define R_IA64_SECREL64LSB 0x67 -#define R_IA64_REL32MSB 0x6c -#define R_IA64_REL32LSB 0x6d -#define R_IA64_REL64MSB 0x6e -#define R_IA64_REL64LSB 0x6f -#define R_IA64_LTV32MSB 0x74 -#define R_IA64_LTV32LSB 0x75 -#define R_IA64_LTV64MSB 0x76 -#define R_IA64_LTV64LSB 0x77 -#define R_IA64_PCREL21BI 0x79 -#define R_IA64_PCREL22 0x7a -#define R_IA64_PCREL64I 0x7b -#define R_IA64_IPLTMSB 0x80 -#define R_IA64_IPLTLSB 0x81 -#define R_IA64_COPY 0x84 -#define R_IA64_SUB 0x85 -#define R_IA64_LTOFF22X 0x86 -#define R_IA64_LDXMOV 0x87 -#define R_IA64_TPREL14 0x91 -#define R_IA64_TPREL22 0x92 -#define R_IA64_TPREL64I 0x93 -#define R_IA64_TPREL64MSB 0x96 -#define R_IA64_TPREL64LSB 0x97 -#define R_IA64_LTOFF_TPREL22 0x9a -#define R_IA64_DTPMOD64MSB 0xa6 -#define R_IA64_DTPMOD64LSB 0xa7 -#define R_IA64_LTOFF_DTPMOD22 0xaa -#define R_IA64_DTPREL14 0xb1 -#define R_IA64_DTPREL22 0xb2 -#define R_IA64_DTPREL64I 0xb3 -#define R_IA64_DTPREL32MSB 0xb4 -#define R_IA64_DTPREL32LSB 0xb5 -#define R_IA64_DTPREL64MSB 0xb6 -#define R_IA64_DTPREL64LSB 0xb7 -#define R_IA64_LTOFF_DTPREL22 0xba - - - - -#define R_SH_NONE 0 -#define R_SH_DIR32 1 -#define R_SH_REL32 2 -#define R_SH_DIR8WPN 3 -#define R_SH_IND12W 4 -#define R_SH_DIR8WPL 5 -#define R_SH_DIR8WPZ 6 -#define R_SH_DIR8BP 7 -#define R_SH_DIR8W 8 -#define R_SH_DIR8L 9 -#define R_SH_SWITCH16 25 -#define R_SH_SWITCH32 26 -#define R_SH_USES 27 -#define R_SH_COUNT 28 -#define R_SH_ALIGN 29 -#define R_SH_CODE 30 -#define R_SH_DATA 31 -#define R_SH_LABEL 32 -#define R_SH_SWITCH8 33 -#define R_SH_GNU_VTINHERIT 34 -#define R_SH_GNU_VTENTRY 35 -#define R_SH_TLS_GD_32 144 -#define R_SH_TLS_LD_32 145 -#define R_SH_TLS_LDO_32 146 -#define R_SH_TLS_IE_32 147 -#define R_SH_TLS_LE_32 148 -#define R_SH_TLS_DTPMOD32 149 -#define R_SH_TLS_DTPOFF32 150 -#define R_SH_TLS_TPOFF32 151 -#define R_SH_GOT32 160 -#define R_SH_PLT32 161 -#define R_SH_COPY 162 -#define R_SH_GLOB_DAT 163 -#define R_SH_JMP_SLOT 164 -#define R_SH_RELATIVE 165 -#define R_SH_GOTOFF 166 -#define R_SH_GOTPC 167 - -#define R_SH_NUM 256 - - - -#define R_390_NONE 0 -#define R_390_8 1 -#define R_390_12 2 -#define R_390_16 3 -#define R_390_32 4 -#define R_390_PC32 5 -#define R_390_GOT12 6 -#define R_390_GOT32 7 -#define R_390_PLT32 8 -#define R_390_COPY 9 -#define R_390_GLOB_DAT 10 -#define R_390_JMP_SLOT 11 -#define R_390_RELATIVE 12 -#define R_390_GOTOFF32 13 -#define R_390_GOTPC 14 -#define R_390_GOT16 15 -#define R_390_PC16 16 -#define R_390_PC16DBL 17 -#define R_390_PLT16DBL 18 -#define R_390_PC32DBL 19 -#define R_390_PLT32DBL 20 -#define R_390_GOTPCDBL 21 -#define R_390_64 22 -#define R_390_PC64 23 -#define R_390_GOT64 24 -#define R_390_PLT64 25 -#define R_390_GOTENT 26 -#define R_390_GOTOFF16 27 -#define R_390_GOTOFF64 28 -#define R_390_GOTPLT12 29 -#define R_390_GOTPLT16 30 -#define R_390_GOTPLT32 31 -#define R_390_GOTPLT64 32 -#define R_390_GOTPLTENT 33 -#define R_390_PLTOFF16 34 -#define R_390_PLTOFF32 35 -#define R_390_PLTOFF64 36 -#define R_390_TLS_LOAD 37 -#define R_390_TLS_GDCALL 38 - -#define R_390_TLS_LDCALL 39 - -#define R_390_TLS_GD32 40 - -#define R_390_TLS_GD64 41 - -#define R_390_TLS_GOTIE12 42 - -#define R_390_TLS_GOTIE32 43 - -#define R_390_TLS_GOTIE64 44 - -#define R_390_TLS_LDM32 45 - -#define R_390_TLS_LDM64 46 - -#define R_390_TLS_IE32 47 - -#define R_390_TLS_IE64 48 - -#define R_390_TLS_IEENT 49 - -#define R_390_TLS_LE32 50 - -#define R_390_TLS_LE64 51 - -#define R_390_TLS_LDO32 52 - -#define R_390_TLS_LDO64 53 - -#define R_390_TLS_DTPMOD 54 -#define R_390_TLS_DTPOFF 55 -#define R_390_TLS_TPOFF 56 - -#define R_390_20 57 -#define R_390_GOT20 58 -#define R_390_GOTPLT20 59 -#define R_390_TLS_GOTIE20 60 - - -#define R_390_NUM 61 - - - -#define R_CRIS_NONE 0 -#define R_CRIS_8 1 -#define R_CRIS_16 2 -#define R_CRIS_32 3 -#define R_CRIS_8_PCREL 4 -#define R_CRIS_16_PCREL 5 -#define R_CRIS_32_PCREL 6 -#define R_CRIS_GNU_VTINHERIT 7 -#define R_CRIS_GNU_VTENTRY 8 -#define R_CRIS_COPY 9 -#define R_CRIS_GLOB_DAT 10 -#define R_CRIS_JUMP_SLOT 11 -#define R_CRIS_RELATIVE 12 -#define R_CRIS_16_GOT 13 -#define R_CRIS_32_GOT 14 -#define R_CRIS_16_GOTPLT 15 -#define R_CRIS_32_GOTPLT 16 -#define R_CRIS_32_GOTREL 17 -#define R_CRIS_32_PLT_GOTREL 18 -#define R_CRIS_32_PLT_PCREL 19 - -#define R_CRIS_NUM 20 - - - -#define R_X86_64_NONE 0 -#define R_X86_64_64 1 -#define R_X86_64_PC32 2 -#define R_X86_64_GOT32 3 -#define R_X86_64_PLT32 4 -#define R_X86_64_COPY 5 -#define R_X86_64_GLOB_DAT 6 -#define R_X86_64_JUMP_SLOT 7 -#define R_X86_64_RELATIVE 8 -#define R_X86_64_GOTPCREL 9 - -#define R_X86_64_32 10 -#define R_X86_64_32S 11 -#define R_X86_64_16 12 -#define R_X86_64_PC16 13 -#define R_X86_64_8 14 -#define R_X86_64_PC8 15 -#define R_X86_64_DTPMOD64 16 -#define R_X86_64_DTPOFF64 17 -#define R_X86_64_TPOFF64 18 -#define R_X86_64_TLSGD 19 - -#define R_X86_64_TLSLD 20 - -#define R_X86_64_DTPOFF32 21 -#define R_X86_64_GOTTPOFF 22 - -#define R_X86_64_TPOFF32 23 -#define R_X86_64_PC64 24 -#define R_X86_64_GOTOFF64 25 -#define R_X86_64_GOTPC32 26 -#define R_X86_64_GOT64 27 -#define R_X86_64_GOTPCREL64 28 -#define R_X86_64_GOTPC64 29 -#define R_X86_64_GOTPLT64 30 -#define R_X86_64_PLTOFF64 31 -#define R_X86_64_SIZE32 32 -#define R_X86_64_SIZE64 33 - -#define R_X86_64_GOTPC32_TLSDESC 34 -#define R_X86_64_TLSDESC_CALL 35 - -#define R_X86_64_TLSDESC 36 -#define R_X86_64_IRELATIVE 37 -#define R_X86_64_RELATIVE64 38 -#define R_X86_64_NUM 39 - - - -#define R_MN10300_NONE 0 -#define R_MN10300_32 1 -#define R_MN10300_16 2 -#define R_MN10300_8 3 -#define R_MN10300_PCREL32 4 -#define R_MN10300_PCREL16 5 -#define R_MN10300_PCREL8 6 -#define R_MN10300_GNU_VTINHERIT 7 -#define R_MN10300_GNU_VTENTRY 8 -#define R_MN10300_24 9 -#define R_MN10300_GOTPC32 10 -#define R_MN10300_GOTPC16 11 -#define R_MN10300_GOTOFF32 12 -#define R_MN10300_GOTOFF24 13 -#define R_MN10300_GOTOFF16 14 -#define R_MN10300_PLT32 15 -#define R_MN10300_PLT16 16 -#define R_MN10300_GOT32 17 -#define R_MN10300_GOT24 18 -#define R_MN10300_GOT16 19 -#define R_MN10300_COPY 20 -#define R_MN10300_GLOB_DAT 21 -#define R_MN10300_JMP_SLOT 22 -#define R_MN10300_RELATIVE 23 - -#define R_MN10300_NUM 24 - - - -#define R_M32R_NONE 0 -#define R_M32R_16 1 -#define R_M32R_32 2 -#define R_M32R_24 3 -#define R_M32R_10_PCREL 4 -#define R_M32R_18_PCREL 5 -#define R_M32R_26_PCREL 6 -#define R_M32R_HI16_ULO 7 -#define R_M32R_HI16_SLO 8 -#define R_M32R_LO16 9 -#define R_M32R_SDA16 10 -#define R_M32R_GNU_VTINHERIT 11 -#define R_M32R_GNU_VTENTRY 12 - -#define R_M32R_16_RELA 33 -#define R_M32R_32_RELA 34 -#define R_M32R_24_RELA 35 -#define R_M32R_10_PCREL_RELA 36 -#define R_M32R_18_PCREL_RELA 37 -#define R_M32R_26_PCREL_RELA 38 -#define R_M32R_HI16_ULO_RELA 39 -#define R_M32R_HI16_SLO_RELA 40 -#define R_M32R_LO16_RELA 41 -#define R_M32R_SDA16_RELA 42 -#define R_M32R_RELA_GNU_VTINHERIT 43 -#define R_M32R_RELA_GNU_VTENTRY 44 -#define R_M32R_REL32 45 - -#define R_M32R_GOT24 48 -#define R_M32R_26_PLTREL 49 -#define R_M32R_COPY 50 -#define R_M32R_GLOB_DAT 51 -#define R_M32R_JMP_SLOT 52 -#define R_M32R_RELATIVE 53 -#define R_M32R_GOTOFF 54 -#define R_M32R_GOTPC24 55 -#define R_M32R_GOT16_HI_ULO 56 - -#define R_M32R_GOT16_HI_SLO 57 - -#define R_M32R_GOT16_LO 58 -#define R_M32R_GOTPC_HI_ULO 59 - -#define R_M32R_GOTPC_HI_SLO 60 - -#define R_M32R_GOTPC_LO 61 - -#define R_M32R_GOTOFF_HI_ULO 62 - -#define R_M32R_GOTOFF_HI_SLO 63 - -#define R_M32R_GOTOFF_LO 64 -#define R_M32R_NUM 256 - -#define R_MICROBLAZE_NONE 0 -#define R_MICROBLAZE_32 1 -#define R_MICROBLAZE_32_PCREL 2 -#define R_MICROBLAZE_64_PCREL 3 -#define R_MICROBLAZE_32_PCREL_LO 4 -#define R_MICROBLAZE_64 5 -#define R_MICROBLAZE_32_LO 6 -#define R_MICROBLAZE_SRO32 7 -#define R_MICROBLAZE_SRW32 8 -#define R_MICROBLAZE_64_NONE 9 -#define R_MICROBLAZE_32_SYM_OP_SYM 10 -#define R_MICROBLAZE_GNU_VTINHERIT 11 -#define R_MICROBLAZE_GNU_VTENTRY 12 -#define R_MICROBLAZE_GOTPC_64 13 -#define R_MICROBLAZE_GOT_64 14 -#define R_MICROBLAZE_PLT_64 15 -#define R_MICROBLAZE_REL 16 -#define R_MICROBLAZE_JUMP_SLOT 17 -#define R_MICROBLAZE_GLOB_DAT 18 -#define R_MICROBLAZE_GOTOFF_64 19 -#define R_MICROBLAZE_GOTOFF_32 20 -#define R_MICROBLAZE_COPY 21 -#define R_MICROBLAZE_TLS 22 -#define R_MICROBLAZE_TLSGD 23 -#define R_MICROBLAZE_TLSLD 24 -#define R_MICROBLAZE_TLSDTPMOD32 25 -#define R_MICROBLAZE_TLSDTPREL32 26 -#define R_MICROBLAZE_TLSDTPREL64 27 -#define R_MICROBLAZE_TLSGOTTPREL32 28 -#define R_MICROBLAZE_TLSTPREL32 29 - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/user/include/endian.h b/user/include/endian.h deleted file mode 100644 index 1bd44451..00000000 --- a/user/include/endian.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef _ENDIAN_H -#define _ENDIAN_H - -#include - -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#define __PDP_ENDIAN 3412 - -#if defined(__GNUC__) && defined(__BYTE_ORDER__) -#define __BYTE_ORDER __BYTE_ORDER__ -#else -#include -#endif - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) - -#define BIG_ENDIAN __BIG_ENDIAN -#define LITTLE_ENDIAN __LITTLE_ENDIAN -#define PDP_ENDIAN __PDP_ENDIAN -#define BYTE_ORDER __BYTE_ORDER - -#include - -static __inline uint16_t __bswap16(uint16_t __x) -{ - return __x<<8 | __x>>8; -} - -static __inline uint32_t __bswap32(uint32_t __x) -{ - return __x>>24 | __x>>8&0xff00 | __x<<8&0xff0000 | __x<<24; -} - -static __inline uint64_t __bswap64(uint64_t __x) -{ - return __bswap32(__x)+0ULL<<32 | __bswap32(__x>>32); -} - -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define htobe16(x) __bswap16(x) -#define be16toh(x) __bswap16(x) -#define betoh16(x) __bswap16(x) -#define htobe32(x) __bswap32(x) -#define be32toh(x) __bswap32(x) -#define betoh32(x) __bswap32(x) -#define htobe64(x) __bswap64(x) -#define be64toh(x) __bswap64(x) -#define betoh64(x) __bswap64(x) -#define htole16(x) (uint16_t)(x) -#define le16toh(x) (uint16_t)(x) -#define letoh16(x) (uint16_t)(x) -#define htole32(x) (uint32_t)(x) -#define le32toh(x) (uint32_t)(x) -#define letoh32(x) (uint32_t)(x) -#define htole64(x) (uint64_t)(x) -#define le64toh(x) (uint64_t)(x) -#define letoh64(x) (uint64_t)(x) -#else -#define htobe16(x) (uint16_t)(x) -#define be16toh(x) (uint16_t)(x) -#define betoh16(x) (uint16_t)(x) -#define htobe32(x) (uint32_t)(x) -#define be32toh(x) (uint32_t)(x) -#define betoh32(x) (uint32_t)(x) -#define htobe64(x) (uint64_t)(x) -#define be64toh(x) (uint64_t)(x) -#define betoh64(x) (uint64_t)(x) -#define htole16(x) __bswap16(x) -#define le16toh(x) __bswap16(x) -#define letoh16(x) __bswap16(x) -#define htole32(x) __bswap32(x) -#define le32toh(x) __bswap32(x) -#define letoh32(x) __bswap32(x) -#define htole64(x) __bswap64(x) -#define le64toh(x) __bswap64(x) -#define letoh64(x) __bswap64(x) -#endif - -#endif - -#endif diff --git a/user/include/errno.h b/user/include/errno.h deleted file mode 100644 index 0361b33a..00000000 --- a/user/include/errno.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _ERRNO_H -#define _ERRNO_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - -#ifdef __GNUC__ -__attribute__((const)) -#endif -int *__errno_location(void); -#define errno (*__errno_location()) - -#ifdef _GNU_SOURCE -extern char *program_invocation_short_name, *program_invocation_name; -#endif - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/user/include/features.h b/user/include/features.h deleted file mode 100644 index 294c61dd..00000000 --- a/user/include/features.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _FEATURES_H -#define _FEATURES_H - -#ifdef _ALL_SOURCE -#define _GNU_SOURCE 1 -#endif - -#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \ - && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \ - && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) -#define _BSD_SOURCE 1 -#define _XOPEN_SOURCE 700 -#endif - -#if __STDC_VERSION__ >= 199901L -#define __restrict restrict -#elif !defined(__GNUC__) -#define __restrict -#endif - -#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) -#define __inline inline -#endif - -#if __STDC_VERSION__ >= 201112L -#elif defined(__GNUC__) -#define _Noreturn __attribute__((__noreturn__)) -#else -#define _Noreturn -#endif - -#endif diff --git a/user/include/float.h b/user/include/float.h deleted file mode 100644 index 2b2ad399..00000000 --- a/user/include/float.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _FLOAT_H -#define _FLOAT_H - -#define FLT_RADIX 2 - -#define FLT_TRUE_MIN 1.40129846432481707092e-45F -#define FLT_MIN 1.17549435082228750797e-38F -#define FLT_MAX 3.40282346638528859812e+38F -#define FLT_EPSILON 1.1920928955078125e-07F - -#define FLT_MANT_DIG 24 -#define FLT_MIN_EXP (-125) -#define FLT_MAX_EXP 128 - -#define FLT_DIG 6 -#define FLT_MIN_10_EXP (-37) -#define FLT_MAX_10_EXP 38 - -#define DBL_TRUE_MIN 4.94065645841246544177e-324 -#define DBL_MIN 2.22507385850720138309e-308 -#define DBL_MAX 1.79769313486231570815e+308 -#define DBL_EPSILON 2.22044604925031308085e-16 - -#define DBL_MANT_DIG 53 -#define DBL_MIN_EXP (-1021) -#define DBL_MAX_EXP 1024 - -#define DBL_DIG 15 -#define DBL_MIN_10_EXP (-307) -#define DBL_MAX_10_EXP 308 - -#include - -#endif diff --git a/user/include/fs_syscalls.h b/user/include/fs_syscalls.h deleted file mode 100644 index 58d9e393..00000000 --- a/user/include/fs_syscalls.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _FLOAT_H -#define _FLOAT_H - -#define SYSCALL_CREATE 0 // create a file -#define SYSCALL_SWITCH 1 -#define SYSCALL_DELETE 2 // delete file or directory -#define SYSCALL_OPEN 3 // open a file -#define SYSCALL_READ 4 // read part of a file -#define SYSCALL_WRITE 5 // write part of a file -#define SYSCALL_CLOSE 6 // close a open file -#define SYSCALL_SET_PERM 7 -#define SYSCALL_MEM_MAP 8 -#define SYSCALL_SEEK 9 // change the offset of an open file -#define SYSCALL_MKDIR 10 // create a direcotry -#define SYSCALL_COPY 11 // copy the contents of a file -#define SYSCALL_LS 12 // show contents of a directory - - -//FUNCTIONS THE USER CAN CALL TO INTERACT WITH FILESYSTEM: - -int open(char* filepath, char mode); -//Opens an existing file in filepath with permissions mode. Returns the filedescriptor, or -1 if unsuccessful - -int create(char* filepath, char mode); -//Creates and opens a file in filepath (end of filepath is name of the file) with permissions mode. Returns the filedescriptor, or -1 if unsuccessful - -int mkdir(char* filepath); -//Creates a directory in filepath (end of filepath is name of directory). Returns -1 if unsuccessful. - -int read(int fd, void* buf, int numBytes); -//Reads numBytes bytes from the open file fd (descriptor returned by open). Returns the numeber of bytes read and fills the provided buffer, or -1 if unsuccessful - -int write(int fd, void* buf, int numBytes); -//Writes numBytes bytes from the open file fd (descriptor returned by open). Returns the numeber of bytes written from the provided buffer, or -1 if unsuccessful - -int close(int fd); -//Closes the open file fd (file descriptor returned by open). Returns -1 if unsuccessful - -int seek(int fd, int numBytes); -//Updates the offset of an open file by numBytes. Returns -1 if unsuccessful - -int delete(char* filepath); -//Deletes the file or directory specified by filepath. Returns -1 if unsuccessful - -int copy(char* source, char* dest, char mode); -//Copies the contents of file or directory source into a new directory dest. The new file has permissions mode (if copying directory, put 0 as permission). Returns -1 if unsuccessful - -int ls(char* filepath); -//Lists the contents of a given directory. Returns -1 if unsuccessful. - - -#endif diff --git a/user/include/inttypes.h b/user/include/inttypes.h deleted file mode 100644 index acd023c1..00000000 --- a/user/include/inttypes.h +++ /dev/null @@ -1,233 +0,0 @@ -#ifndef _INTTYPES_H -#define _INTTYPES_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include -#include - -#define __NEED_wchar_t -#include - -typedef struct -{ - intmax_t quot, rem; -} imaxdiv_t; - -intmax_t imaxabs(intmax_t); -imaxdiv_t imaxdiv(intmax_t, intmax_t); - -intmax_t strtoimax(const char *__restrict, char **__restrict, int); -uintmax_t strtoumax(const char *__restrict, char **__restrict, int); - -intmax_t wcstoimax(const wchar_t *__restrict, wchar_t **__restrict, int); -uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int); - -#if UINTPTR_MAX == UINT64_MAX -#define __PRI64 "l" -#define __PRIPTR "l" -#else -#define __PRI64 "ll" -#define __PRIPTR "" -#endif - -#define PRId8 "d" -#define PRId16 "d" -#define PRId32 "d" -#define PRId64 __PRI64 "d" - -#define PRIdLEAST8 "d" -#define PRIdLEAST16 "d" -#define PRIdLEAST32 "d" -#define PRIdLEAST64 __PRI64 "d" - -#define PRIdFAST8 "d" -#define PRIdFAST16 "d" -#define PRIdFAST32 "d" -#define PRIdFAST64 __PRI64 "d" - -#define PRIi8 "i" -#define PRIi16 "i" -#define PRIi32 "i" -#define PRIi64 __PRI64 "i" - -#define PRIiLEAST8 "i" -#define PRIiLEAST16 "i" -#define PRIiLEAST32 "i" -#define PRIiLEAST64 __PRI64 "i" - -#define PRIiFAST8 "i" -#define PRIiFAST16 "i" -#define PRIiFAST32 "i" -#define PRIiFAST64 __PRI64 "i" - -#define PRIo8 "o" -#define PRIo16 "o" -#define PRIo32 "o" -#define PRIo64 __PRI64 "o" - -#define PRIoLEAST8 "o" -#define PRIoLEAST16 "o" -#define PRIoLEAST32 "o" -#define PRIoLEAST64 __PRI64 "o" - -#define PRIoFAST8 "o" -#define PRIoFAST16 "o" -#define PRIoFAST32 "o" -#define PRIoFAST64 __PRI64 "o" - -#define PRIu8 "u" -#define PRIu16 "u" -#define PRIu32 "u" -#define PRIu64 __PRI64 "u" - -#define PRIuLEAST8 "u" -#define PRIuLEAST16 "u" -#define PRIuLEAST32 "u" -#define PRIuLEAST64 __PRI64 "u" - -#define PRIuFAST8 "u" -#define PRIuFAST16 "u" -#define PRIuFAST32 "u" -#define PRIuFAST64 __PRI64 "u" - -#define PRIx8 "x" -#define PRIx16 "x" -#define PRIx32 "x" -#define PRIx64 __PRI64 "x" - -#define PRIxLEAST8 "x" -#define PRIxLEAST16 "x" -#define PRIxLEAST32 "x" -#define PRIxLEAST64 __PRI64 "x" - -#define PRIxFAST8 "x" -#define PRIxFAST16 "x" -#define PRIxFAST32 "x" -#define PRIxFAST64 __PRI64 "x" - -#define PRIX8 "X" -#define PRIX16 "X" -#define PRIX32 "X" -#define PRIX64 __PRI64 "X" - -#define PRIXLEAST8 "X" -#define PRIXLEAST16 "X" -#define PRIXLEAST32 "X" -#define PRIXLEAST64 __PRI64 "X" - -#define PRIXFAST8 "X" -#define PRIXFAST16 "X" -#define PRIXFAST32 "X" -#define PRIXFAST64 __PRI64 "X" - -#define PRIdMAX __PRI64 "d" -#define PRIiMAX __PRI64 "i" -#define PRIoMAX __PRI64 "o" -#define PRIuMAX __PRI64 "u" -#define PRIxMAX __PRI64 "x" -#define PRIXMAX __PRI64 "X" - -#define PRIdPTR __PRIPTR "d" -#define PRIiPTR __PRIPTR "i" -#define PRIoPTR __PRIPTR "o" -#define PRIuPTR __PRIPTR "u" -#define PRIxPTR __PRIPTR "x" -#define PRIXPTR __PRIPTR "X" - -#define SCNd8 "hhd" -#define SCNd16 "hd" -#define SCNd32 "d" -#define SCNd64 __PRI64 "d" - -#define SCNdLEAST8 "hhd" -#define SCNdLEAST16 "hd" -#define SCNdLEAST32 "d" -#define SCNdLEAST64 __PRI64 "d" - -#define SCNdFAST8 "hhd" -#define SCNdFAST16 "d" -#define SCNdFAST32 "d" -#define SCNdFAST64 __PRI64 "d" - -#define SCNi8 "hhi" -#define SCNi16 "hi" -#define SCNi32 "i" -#define SCNi64 __PRI64 "i" - -#define SCNiLEAST8 "hhi" -#define SCNiLEAST16 "hi" -#define SCNiLEAST32 "i" -#define SCNiLEAST64 __PRI64 "i" - -#define SCNiFAST8 "hhi" -#define SCNiFAST16 "i" -#define SCNiFAST32 "i" -#define SCNiFAST64 __PRI64 "i" - -#define SCNu8 "hhu" -#define SCNu16 "hu" -#define SCNu32 "u" -#define SCNu64 __PRI64 "u" - -#define SCNuLEAST8 "hhu" -#define SCNuLEAST16 "hu" -#define SCNuLEAST32 "u" -#define SCNuLEAST64 __PRI64 "u" - -#define SCNuFAST8 "hhu" -#define SCNuFAST16 "u" -#define SCNuFAST32 "u" -#define SCNuFAST64 __PRI64 "u" - -#define SCNo8 "hho" -#define SCNo16 "ho" -#define SCNo32 "o" -#define SCNo64 __PRI64 "o" - -#define SCNoLEAST8 "hho" -#define SCNoLEAST16 "ho" -#define SCNoLEAST32 "o" -#define SCNoLEAST64 __PRI64 "o" - -#define SCNoFAST8 "hho" -#define SCNoFAST16 "o" -#define SCNoFAST32 "o" -#define SCNoFAST64 __PRI64 "o" - -#define SCNx8 "hhx" -#define SCNx16 "hx" -#define SCNx32 "x" -#define SCNx64 __PRI64 "x" - -#define SCNxLEAST8 "hhx" -#define SCNxLEAST16 "hx" -#define SCNxLEAST32 "x" -#define SCNxLEAST64 __PRI64 "x" - -#define SCNxFAST8 "hhx" -#define SCNxFAST16 "x" -#define SCNxFAST32 "x" -#define SCNxFAST64 __PRI64 "x" - -#define SCNdMAX __PRI64 "d" -#define SCNiMAX __PRI64 "i" -#define SCNoMAX __PRI64 "o" -#define SCNuMAX __PRI64 "u" -#define SCNxMAX __PRI64 "x" - -#define SCNdPTR __PRIPTR "d" -#define SCNiPTR __PRIPTR "i" -#define SCNoPTR __PRIPTR "o" -#define SCNuPTR __PRIPTR "u" -#define SCNxPTR __PRIPTR "x" - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/user/include/limits.h b/user/include/limits.h deleted file mode 100644 index f9805a1e..00000000 --- a/user/include/limits.h +++ /dev/null @@ -1,154 +0,0 @@ -#ifndef _LIMITS_H -#define _LIMITS_H - -#include - -/* Most limits are system-specific */ - -#include - -/* Support signed or unsigned plain-char */ - -#if '\0'-1 > 0 -#define CHAR_MIN 0 -#define CHAR_MAX 255 -#else -#define CHAR_MIN (-128) -#define CHAR_MAX 127 -#endif - -/* Some universal constants... */ - -#define CHAR_BIT 8 -#define SCHAR_MIN (-128) -#define SCHAR_MAX 127 -#define UCHAR_MAX 255 -#define SHRT_MIN (-1-0x7fff) -#define SHRT_MAX 0x7fff -#define USHRT_MAX 0xffff -#define INT_MIN (-1-0x7fffffff) -#define INT_MAX 0x7fffffff -#define UINT_MAX 0xffffffffU -#define LONG_MIN (-LONG_MAX-1) -#define ULONG_MAX (2UL*LONG_MAX+1) -#define LLONG_MIN (-LLONG_MAX-1) -#define ULLONG_MAX (2ULL*LLONG_MAX+1) - -#define MB_LEN_MAX 4 - -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) - -#define PIPE_BUF 4096 -#ifdef PAGE_SIZE -#define PAGESIZE PAGE_SIZE -#endif -#define FILESIZEBITS 64 -#define NAME_MAX 255 -#define SYMLINK_MAX 255 -#define PATH_MAX 4096 -#define NZERO 20 -#define NGROUPS_MAX 32 -#define ARG_MAX 131072 -#define IOV_MAX 1024 -#define SYMLOOP_MAX 40 -#define WORD_BIT 32 -#define SSIZE_MAX LONG_MAX -#define TZNAME_MAX 6 -#define TTY_NAME_MAX 32 -#define HOST_NAME_MAX 255 - -/* Implementation choices... */ - -#define PTHREAD_KEYS_MAX 128 -#define PTHREAD_STACK_MIN 2048 -#define PTHREAD_DESTRUCTOR_ITERATIONS 4 -#define SEM_VALUE_MAX 0x7fffffff -#define SEM_NSEMS_MAX 256 -#define DELAYTIMER_MAX 0x7fffffff -#define MQ_PRIO_MAX 32768 -#define LOGIN_NAME_MAX 256 - -/* Arbitrary numbers... */ - -#define BC_BASE_MAX 99 -#define BC_DIM_MAX 2048 -#define BC_SCALE_MAX 99 -#define BC_STRING_MAX 1000 -#define CHARCLASS_NAME_MAX 14 -#define COLL_WEIGHTS_MAX 2 -#define EXPR_NEST_MAX 32 -#define LINE_MAX 4096 -#define RE_DUP_MAX 255 - -#define NL_ARGMAX 9 -#define NL_LANGMAX 32 -#define NL_MSGMAX 32767 -#define NL_SETMAX 255 -#define NL_TEXTMAX 2048 - -#endif - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) \ - || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) - -#define NL_NMAX 16 - -#endif - -/* POSIX/SUS requirements follow. These numbers come directly - * from SUS and have nothing to do with the host system. */ - -#define _POSIX_AIO_LISTIO_MAX 2 -#define _POSIX_AIO_MAX 1 -#define _POSIX_ARG_MAX 4096 -#define _POSIX_CHILD_MAX 25 -#define _POSIX_CLOCKRES_MIN 20000000 -#define _POSIX_DELAYTIMER_MAX 32 -#define _POSIX_HOST_NAME_MAX 255 -#define _POSIX_LINK_MAX 8 -#define _POSIX_LOGIN_NAME_MAX 9 -#define _POSIX_MAX_CANON 255 -#define _POSIX_MAX_INPUT 255 -#define _POSIX_MQ_OPEN_MAX 8 -#define _POSIX_MQ_PRIO_MAX 32 -#define _POSIX_NAME_MAX 14 -#define _POSIX_NGROUPS_MAX 8 -#define _POSIX_OPEN_MAX 20 -#define _POSIX_PATH_MAX 256 -#define _POSIX_PIPE_BUF 512 -#define _POSIX_RE_DUP_MAX 255 -#define _POSIX_RTSIG_MAX 8 -#define _POSIX_SEM_NSEMS_MAX 256 -#define _POSIX_SEM_VALUE_MAX 32767 -#define _POSIX_SIGQUEUE_MAX 32 -#define _POSIX_SSIZE_MAX 32767 -#define _POSIX_STREAM_MAX 8 -#define _POSIX_SS_REPL_MAX 4 -#define _POSIX_SYMLINK_MAX 255 -#define _POSIX_SYMLOOP_MAX 8 -#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 -#define _POSIX_THREAD_KEYS_MAX 128 -#define _POSIX_THREAD_THREADS_MAX 64 -#define _POSIX_TIMER_MAX 32 -#define _POSIX_TRACE_EVENT_NAME_MAX 30 -#define _POSIX_TRACE_NAME_MAX 8 -#define _POSIX_TRACE_SYS_MAX 8 -#define _POSIX_TRACE_USER_EVENT_MAX 32 -#define _POSIX_TTY_NAME_MAX 9 -#define _POSIX_TZNAME_MAX 6 -#define _POSIX2_BC_BASE_MAX 99 -#define _POSIX2_BC_DIM_MAX 2048 -#define _POSIX2_BC_SCALE_MAX 99 -#define _POSIX2_BC_STRING_MAX 1000 -#define _POSIX2_CHARCLASS_NAME_MAX 14 -#define _POSIX2_COLL_WEIGHTS_MAX 2 -#define _POSIX2_EXPR_NEST_MAX 32 -#define _POSIX2_LINE_MAX 2048 -#define _POSIX2_RE_DUP_MAX 255 - -#define _XOPEN_IOV_MAX 16 -#define _XOPEN_NAME_MAX 255 -#define _XOPEN_PATH_MAX 1024 - -#endif diff --git a/user/include/malloc_syscalls.h b/user/include/malloc_syscalls.h deleted file mode 100644 index ffcd2340..00000000 --- a/user/include/malloc_syscalls.h +++ /dev/null @@ -1,43 +0,0 @@ -#include -//#include "../arch/arm/syscall_arch.h" -#include "stdint.h" - -/*********************************** - * SYSCALLS for Malloc * - ************************************/ - -#define SYSCALL_MALLOC 13 -#define SYSCALL_ALIGNED_ALLOC 14 -#define SYSCALL_FREE 15 - -/** - * malloc does a system call to allocate memory on the user heap - * - * @param size of the block of memory allocated - * @param uint32_t size - * @return returns a pointer to the allocated block of memory - returns 0 if size is less than 1; - */ -void* malloc(uint32_t size); - -/** - * aligned alloc does a system call to allocate memory on the user heap - * according to a specified alignemnt - * - * @param size of the block of memory allocated, and alignment desired - * @param uint32_t size >= 0, uint32_t alignment >=0 - * @return returns a pointer to the allocated block of memory - * that is a multiple of the specified allignement - * returns 0 if size or alignment are less than 1 - */ -void* aligned_alloc(uint32_t size, uint32_t alignment); - -/** - * free does a system call to free an allocated block of memory on the heap - * - * @param pointer to a block of memeory on the heap - * @param void* ptr - * @return nothing returned - */ -void free(void* ptr); - diff --git a/user/include/math.h b/user/include/math.h deleted file mode 100644 index 6ac91da2..00000000 --- a/user/include/math.h +++ /dev/null @@ -1,430 +0,0 @@ -#ifndef _MATH_H -#define _MATH_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#define __NEED_float_t -#define __NEED_double_t -#include - -#if 100*__GNUC__+__GNUC_MINOR__ >= 303 -#define NAN __builtin_nanf("") -#define INFINITY __builtin_inff() -#else -#define NAN (0.0f/0.0f) -#define INFINITY 1e5000f -#endif - -#define HUGE_VALF INFINITY -#define HUGE_VAL ((double)INFINITY) -#define HUGE_VALL ((long double)INFINITY) - -#define MATH_ERRNO 1 -#define MATH_ERREXCEPT 2 -#define math_errhandling 2 - -#define FP_ILOGBNAN (-1-(int)(((unsigned)-1)>>1)) -#define FP_ILOGB0 FP_ILOGBNAN - -#define FP_NAN 0 -#define FP_INFINITE 1 -#define FP_ZERO 2 -#define FP_SUBNORMAL 3 -#define FP_NORMAL 4 - -int __fpclassify(double); -int __fpclassifyf(float); -int __fpclassifyl(long double); - -static __inline unsigned __FLOAT_BITS(float __f) -{ - union {float __f; unsigned __i;} __u; - __u.__f = __f; - return __u.__i; -} -static __inline unsigned long long __DOUBLE_BITS(double __f) -{ - union {double __f; unsigned long long __i;} __u; - __u.__f = __f; - return __u.__i; -} - -#define fpclassify(x) ( \ - sizeof(x) == sizeof(float) ? __fpclassifyf(x) : \ - sizeof(x) == sizeof(double) ? __fpclassify(x) : \ - __fpclassifyl(x) ) - -#define isinf(x) ( \ - sizeof(x) == sizeof(float) ? (__FLOAT_BITS(x) & 0x7fffffff) == 0x7f800000 : \ - sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & -1ULL>>1) == 0x7ffULL<<52 : \ - __fpclassifyl(x) == FP_INFINITE) - -#define isnan(x) ( \ - sizeof(x) == sizeof(float) ? (__FLOAT_BITS(x) & 0x7fffffff) > 0x7f800000 : \ - sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & -1ULL>>1) > 0x7ffULL<<52 : \ - __fpclassifyl(x) == FP_NAN) - -#define isnormal(x) ( \ - sizeof(x) == sizeof(float) ? ((__FLOAT_BITS(x)+0x00800000) & 0x7fffffff) >= 0x01000000 : \ - sizeof(x) == sizeof(double) ? ((__DOUBLE_BITS(x)+(1ULL<<52)) & -1ULL>>1) >= 1ULL<<53 : \ - __fpclassifyl(x) == FP_NORMAL) - -#define isfinite(x) ( \ - sizeof(x) == sizeof(float) ? (__FLOAT_BITS(x) & 0x7fffffff) < 0x7f800000 : \ - sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & -1ULL>>1) < 0x7ffULL<<52 : \ - __fpclassifyl(x) > FP_INFINITE) - -int __signbit(double); -int __signbitf(float); -int __signbitl(long double); - -#define signbit(x) ( \ - sizeof(x) == sizeof(float) ? (int)(__FLOAT_BITS(x)>>31) : \ - sizeof(x) == sizeof(double) ? (int)(__DOUBLE_BITS(x)>>63) : \ - __signbitl(x) ) - -#define isunordered(x,y) (isnan((x)) ? ((void)(y),1) : isnan((y))) - -#define __ISREL_DEF(rel, op, type) \ -static __inline int __is##rel(type __x, type __y) \ -{ return !isunordered(__x,__y) && __x op __y; } - -__ISREL_DEF(lessf, <, float_t) -__ISREL_DEF(less, <, double_t) -__ISREL_DEF(lessl, <, long double) -__ISREL_DEF(lessequalf, <=, float_t) -__ISREL_DEF(lessequal, <=, double_t) -__ISREL_DEF(lessequall, <=, long double) -__ISREL_DEF(lessgreaterf, !=, float_t) -__ISREL_DEF(lessgreater, !=, double_t) -__ISREL_DEF(lessgreaterl, !=, long double) -__ISREL_DEF(greaterf, >, float_t) -__ISREL_DEF(greater, >, double_t) -__ISREL_DEF(greaterl, >, long double) -__ISREL_DEF(greaterequalf, >=, float_t) -__ISREL_DEF(greaterequal, >=, double_t) -__ISREL_DEF(greaterequall, >=, long double) - -#define __tg_pred_2(x, y, p) ( \ - sizeof((x)+(y)) == sizeof(float) ? p##f(x, y) : \ - sizeof((x)+(y)) == sizeof(double) ? p(x, y) : \ - p##l(x, y) ) - -#define isless(x, y) __tg_pred_2(x, y, __isless) -#define islessequal(x, y) __tg_pred_2(x, y, __islessequal) -#define islessgreater(x, y) __tg_pred_2(x, y, __islessgreater) -#define isgreater(x, y) __tg_pred_2(x, y, __isgreater) -#define isgreaterequal(x, y) __tg_pred_2(x, y, __isgreaterequal) - -double acos(double); -float acosf(float); -long double acosl(long double); - -double acosh(double); -float acoshf(float); -long double acoshl(long double); - -double asin(double); -float asinf(float); -long double asinl(long double); - -double asinh(double); -float asinhf(float); -long double asinhl(long double); - -double atan(double); -float atanf(float); -long double atanl(long double); - -double atan2(double, double); -float atan2f(float, float); -long double atan2l(long double, long double); - -double atanh(double); -float atanhf(float); -long double atanhl(long double); - -double cbrt(double); -float cbrtf(float); -long double cbrtl(long double); - -double ceil(double); -float ceilf(float); -long double ceill(long double); - -double copysign(double, double); -float copysignf(float, float); -long double copysignl(long double, long double); - -double cos(double); -float cosf(float); -long double cosl(long double); - -double cosh(double); -float coshf(float); -long double coshl(long double); - -double erf(double); -float erff(float); -long double erfl(long double); - -double erfc(double); -float erfcf(float); -long double erfcl(long double); - -double exp(double); -float expf(float); -long double expl(long double); - -double exp2(double); -float exp2f(float); -long double exp2l(long double); - -double expm1(double); -float expm1f(float); -long double expm1l(long double); - -double fabs(double); -float fabsf(float); -long double fabsl(long double); - -double fdim(double, double); -float fdimf(float, float); -long double fdiml(long double, long double); - -double floor(double); -float floorf(float); -long double floorl(long double); - -double fma(double, double, double); -float fmaf(float, float, float); -long double fmal(long double, long double, long double); - -double fmax(double, double); -float fmaxf(float, float); -long double fmaxl(long double, long double); - -double fmin(double, double); -float fminf(float, float); -long double fminl(long double, long double); - -double fmod(double, double); -float fmodf(float, float); -long double fmodl(long double, long double); - -double frexp(double, int *); -float frexpf(float, int *); -long double frexpl(long double, int *); - -double hypot(double, double); -float hypotf(float, float); -long double hypotl(long double, long double); - -int ilogb(double); -int ilogbf(float); -int ilogbl(long double); - -double ldexp(double, int); -float ldexpf(float, int); -long double ldexpl(long double, int); - -double lgamma(double); -float lgammaf(float); -long double lgammal(long double); - -long long llrint(double); -long long llrintf(float); -long long llrintl(long double); - -long long llround(double); -long long llroundf(float); -long long llroundl(long double); - -double log(double); -float logf(float); -long double logl(long double); - -double log10(double); -float log10f(float); -long double log10l(long double); - -double log1p(double); -float log1pf(float); -long double log1pl(long double); - -double log2(double); -float log2f(float); -long double log2l(long double); - -double logb(double); -float logbf(float); -long double logbl(long double); - -long lrint(double); -long lrintf(float); -long lrintl(long double); - -long lround(double); -long lroundf(float); -long lroundl(long double); - -double modf(double, double *); -float modff(float, float *); -long double modfl(long double, long double *); - -double nan(const char *); -float nanf(const char *); -long double nanl(const char *); - -double nearbyint(double); -float nearbyintf(float); -long double nearbyintl(long double); - -double nextafter(double, double); -float nextafterf(float, float); -long double nextafterl(long double, long double); - -double nexttoward(double, long double); -float nexttowardf(float, long double); -long double nexttowardl(long double, long double); - -double pow(double, double); -float powf(float, float); -long double powl(long double, long double); - -double remainder(double, double); -float remainderf(float, float); -long double remainderl(long double, long double); - -double remquo(double, double, int *); -float remquof(float, float, int *); -long double remquol(long double, long double, int *); - -double rint(double); -float rintf(float); -long double rintl(long double); - -double round(double); -float roundf(float); -long double roundl(long double); - -double scalbln(double, long); -float scalblnf(float, long); -long double scalblnl(long double, long); - -double scalbn(double, int); -float scalbnf(float, int); -long double scalbnl(long double, int); - -double sin(double); -float sinf(float); -long double sinl(long double); - -double sinh(double); -float sinhf(float); -long double sinhl(long double); - -double sqrt(double); -float sqrtf(float); -long double sqrtl(long double); - -double tan(double); -float tanf(float); -long double tanl(long double); - -double tanh(double); -float tanhf(float); -long double tanhl(long double); - -double tgamma(double); -float tgammaf(float); -long double tgammal(long double); - -double trunc(double); -float truncf(float); -long double truncl(long double); - - -#if defined(_XOPEN_SOURCE) || defined(_BSD_SOURCE) -#undef MAXFLOAT -#define MAXFLOAT 3.40282346638528859812e+38F -#endif - -#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define M_E 2.7182818284590452354 /* e */ -#define M_LOG2E 1.4426950408889634074 /* log_2 e */ -#define M_LOG10E 0.43429448190325182765 /* log_10 e */ -#define M_LN2 0.69314718055994530942 /* log_e 2 */ -#define M_LN10 2.30258509299404568402 /* log_e 10 */ -#define M_PI 3.14159265358979323846 /* pi */ -#define M_PI_2 1.57079632679489661923 /* pi/2 */ -#define M_PI_4 0.78539816339744830962 /* pi/4 */ -#define M_1_PI 0.31830988618379067154 /* 1/pi */ -#define M_2_PI 0.63661977236758134308 /* 2/pi */ -#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ -#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ -#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ - -extern int signgam; - -double j0(double); -double j1(double); -double jn(int, double); - -double y0(double); -double y1(double); -double yn(int, double); -#endif - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define HUGE 3.40282346638528859812e+38F - -double drem(double, double); -float dremf(float, float); - -int finite(double); -int finitef(float); - -double scalb(double, double); -float scalbf(float, float); - -double significand(double); -float significandf(float); - -double lgamma_r(double, int*); -float lgammaf_r(float, int*); - -float j0f(float); -float j1f(float); -float jnf(int, float); - -float y0f(float); -float y1f(float); -float ynf(int, float); -#endif - -#ifdef _GNU_SOURCE -long double lgammal_r(long double, int*); - -void sincos(double, double*, double*); -void sincosf(float, float*, float*); -void sincosl(long double, long double*, long double*); - -double exp10(double); -float exp10f(float); -long double exp10l(long double); - -double pow10(double); -float pow10f(float); -long double pow10l(long double); -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/user/include/stdarg.h b/user/include/stdarg.h deleted file mode 100644 index 60d4e2af..00000000 --- a/user/include/stdarg.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _STDARG_H -#define _STDARG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define __NEED_va_list - -#include - -#if __GNUC__ >= 3 -#define va_start(v,l) __builtin_va_start(v,l) -#define va_end(v) __builtin_va_end(v) -#define va_arg(v,l) __builtin_va_arg(v,l) -#define va_copy(d,s) __builtin_va_copy(d,s) -#else -#include -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/user/include/stdint.h b/user/include/stdint.h deleted file mode 100644 index ad6aaead..00000000 --- a/user/include/stdint.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef _STDINT_H -#define _STDINT_H - -#define __NEED_int8_t -#define __NEED_int16_t -#define __NEED_int32_t -#define __NEED_int64_t - -#define __NEED_uint8_t -#define __NEED_uint16_t -#define __NEED_uint32_t -#define __NEED_uint64_t - -#define __NEED_intptr_t -#define __NEED_uintptr_t - -#define __NEED_intmax_t -#define __NEED_uintmax_t - -#include - -typedef int8_t int_fast8_t; -typedef int64_t int_fast64_t; - -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; - -typedef uint8_t uint_fast8_t; -typedef uint64_t uint_fast64_t; - -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -#define INT8_MIN (-1-0x7f) -#define INT16_MIN (-1-0x7fff) -#define INT32_MIN (-1-0x7fffffff) -#define INT64_MIN (-1-0x7fffffffffffffff) - -#define INT8_MAX (0x7f) -#define INT16_MAX (0x7fff) -#define INT32_MAX (0x7fffffff) -#define INT64_MAX (0x7fffffffffffffff) - -#define UINT8_MAX (0xff) -#define UINT16_MAX (0xffff) -#define UINT32_MAX (0xffffffff) -#define UINT64_MAX (0xffffffffffffffff) - -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST64_MIN INT64_MIN - -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST64_MIN INT64_MIN - -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST64_MAX INT64_MAX - -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MAX INT64_MAX - -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST64_MAX UINT64_MAX - -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -#define WINT_MIN 0 -#define WINT_MAX UINT32_MAX - -#if L'\0'-1 > 0 -#define WCHAR_MAX (0xffffffffu+L'\0') -#define WCHAR_MIN (0+L'\0') -#else -#define WCHAR_MAX (0x7fffffff+L'\0') -#define WCHAR_MIN (-1-0x7fffffff+L'\0') -#endif - -#define SIG_ATOMIC_MIN INT32_MIN -#define SIG_ATOMIC_MAX INT32_MAX - -#include - -#define INT8_C(c) c -#define INT16_C(c) c -#define INT32_C(c) c - -#define UINT8_C(c) c -#define UINT16_C(c) c -#define UINT32_C(c) c ## U - -#if UINTPTR_MAX == UINT64_MAX -#define INT64_C(c) c ## L -#define UINT64_C(c) c ## UL -#define INTMAX_C(c) c ## L -#define UINTMAX_C(c) c ## UL -#else -#define INT64_C(c) c ## LL -#define UINT64_C(c) c ## ULL -#define INTMAX_C(c) c ## LL -#define UINTMAX_C(c) c ## ULL -#endif - -#endif diff --git a/user/include/stdio.h b/user/include/stdio.h deleted file mode 100644 index 793e3fbe..00000000 --- a/user/include/stdio.h +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef _STDIO_H -#define _STDIO_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#define SYSCALL_PRINTF 16 -#define SYSCALL_DUMMY 99 - -#define __NEED_FILE -#define __NEED___isoc_va_list -#define __NEED_size_t - -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ - || defined(_BSD_SOURCE) -#define __NEED_ssize_t -#define __NEED_off_t -#define __NEED_va_list -#endif - -#include - -#ifdef __cplusplus -#define NULL 0L -#else -#define NULL ((void*)0) -#endif - -#undef EOF -#define EOF (-1) - -#undef SEEK_SET -#undef SEEK_CUR -#undef SEEK_END -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 - -#define _IOFBF 0 -#define _IOLBF 1 -#define _IONBF 2 - -#define BUFSIZ 1024 -#define FILENAME_MAX 4096 -#define FOPEN_MAX 1000 -#define TMP_MAX 10000 -#define L_tmpnam 20 - -typedef union _G_fpos64_t { - char __opaque[16]; - double __align; -} fpos_t; - -extern FILE *const stdin; -extern FILE *const stdout; -extern FILE *const stderr; - -#define stdin (stdin) -#define stdout (stdout) -#define stderr (stderr) - -FILE *fopen(const char *__restrict, const char *__restrict); -FILE *freopen(const char *__restrict, const char *__restrict, FILE *__restrict); -int fclose(FILE *); - -int remove(const char *); -int rename(const char *, const char *); - -int feof(FILE *); -int ferror(FILE *); -int fflush(FILE *); -void clearerr(FILE *); - -int fseek(FILE *, long, int); -long ftell(FILE *); -void rewind(FILE *); - -int fgetpos(FILE *__restrict, fpos_t *__restrict); -int fsetpos(FILE *, const fpos_t *); - -size_t fread(void *__restrict, size_t, size_t, FILE *__restrict); -size_t fwrite(const void *__restrict, size_t, size_t, FILE *__restrict); - -int fgetc(FILE *); -int getc(FILE *); -int getchar(void); -int ungetc(int, FILE *); - -int fputc(int, FILE *); -int putc(int, FILE *); -int putchar(int); - -char *fgets(char *__restrict, int, FILE *__restrict); -#if __STDC_VERSION__ < 201112L -char *gets(char *); -#endif - -int fputs(const char *__restrict, FILE *__restrict); -int puts(const char *); - -int printf(const char *__restrict, ...); -int fprintf(FILE *__restrict, const char *__restrict, ...); -int sprintf(char *__restrict, const char *__restrict, ...); -int snprintf(char *__restrict, size_t, const char *__restrict, ...); - -int vprintf(const char *__restrict, __isoc_va_list); -int vfprintf(FILE *__restrict, const char *__restrict, __isoc_va_list); -int vsprintf(char *__restrict, const char *__restrict, __isoc_va_list); -int vsnprintf(char *__restrict, size_t, const char *__restrict, __isoc_va_list); - -int scanf(const char *__restrict, ...); -int fscanf(FILE *__restrict, const char *__restrict, ...); -int sscanf(const char *__restrict, const char *__restrict, ...); -int vscanf(const char *__restrict, __isoc_va_list); -int vfscanf(FILE *__restrict, const char *__restrict, __isoc_va_list); -int vsscanf(const char *__restrict, const char *__restrict, __isoc_va_list); - -void perror(const char *); - -int setvbuf(FILE *__restrict, char *__restrict, int, size_t); -void setbuf(FILE *__restrict, char *__restrict); - -char *tmpnam(char *); -FILE *tmpfile(void); - -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ - || defined(_BSD_SOURCE) -FILE *fmemopen(void *__restrict, size_t, const char *__restrict); -FILE *open_memstream(char **, size_t *); -FILE *fdopen(int, const char *); -FILE *popen(const char *, const char *); -int pclose(FILE *); -int fileno(FILE *); -int fseeko(FILE *, off_t, int); -off_t ftello(FILE *); -int dprintf(int, const char *__restrict, ...); -int vdprintf(int, const char *__restrict, __isoc_va_list); -void flockfile(FILE *); -int ftrylockfile(FILE *); -void funlockfile(FILE *); -int getc_unlocked(FILE *); -int getchar_unlocked(void); -int putc_unlocked(int, FILE *); -int putchar_unlocked(int); -ssize_t getdelim(char **__restrict, size_t *__restrict, int, FILE *__restrict); -ssize_t getline(char **__restrict, size_t *__restrict, FILE *__restrict); -int renameat(int, const char *, int, const char *); -char *ctermid(char *); -#define L_ctermid 20 -#endif - - -#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ - || defined(_BSD_SOURCE) -#define P_tmpdir "/tmp" -char *tempnam(const char *, const char *); -#endif - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define L_cuserid 20 -char *cuserid(char *); -void setlinebuf(FILE *); -void setbuffer(FILE *, char *, size_t); -int fgetc_unlocked(FILE *); -int fputc_unlocked(int, FILE *); -int fflush_unlocked(FILE *); -size_t fread_unlocked(void *, size_t, size_t, FILE *); -size_t fwrite_unlocked(const void *, size_t, size_t, FILE *); -void clearerr_unlocked(FILE *); -int feof_unlocked(FILE *); -int ferror_unlocked(FILE *); -int fileno_unlocked(FILE *); -int getw(FILE *); -int putw(int, FILE *); -char *fgetln(FILE *, size_t *); -int asprintf(char **, const char *, ...); -int vasprintf(char **, const char *, __isoc_va_list); -#endif - -#ifdef _GNU_SOURCE -char *fgets_unlocked(char *, int, FILE *); -int fputs_unlocked(const char *, FILE *); -#endif - -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) -#define tmpfile64 tmpfile -#define fopen64 fopen -#define freopen64 freopen -#define fseeko64 fseeko -#define ftello64 ftello -#define fgetpos64 fgetpos -#define fsetpos64 fsetpos -#define fpos64_t fpos_t -#define off64_t off_t -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/user/include/stdlib.h b/user/include/stdlib.h deleted file mode 100644 index f034c6e5..00000000 --- a/user/include/stdlib.h +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef _STDLIB_H -#define _STDLIB_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#ifdef __cplusplus -#define NULL 0L -#else -#define NULL ((void*)0) -#endif - -#define __NEED_size_t -#define __NEED_wchar_t - -#include - -int atoi (const char *); -long atol (const char *); -long long atoll (const char *); -double atof (const char *); - -float strtof (const char *__restrict, char **__restrict); -double strtod (const char *__restrict, char **__restrict); -long double strtold (const char *__restrict, char **__restrict); - -long strtol (const char *__restrict, char **__restrict, int); -unsigned long strtoul (const char *__restrict, char **__restrict, int); -long long strtoll (const char *__restrict, char **__restrict, int); -unsigned long long strtoull (const char *__restrict, char **__restrict, int); - -int rand (void); -void srand (unsigned); - -void *malloc (size_t); -void *calloc (size_t, size_t); -void *realloc (void *, size_t); -void free (void *); -void *aligned_alloc(size_t alignment, size_t size); - -_Noreturn void abort (void); -int atexit (void (*) (void)); -_Noreturn void exit (int); -_Noreturn void _Exit (int); -int at_quick_exit (void (*) (void)); -_Noreturn void quick_exit (int); - -char *getenv (const char *); - -int system (const char *); - -void *bsearch (const void *, const void *, size_t, size_t, int (*)(const void *, const void *)); -void qsort (void *, size_t, size_t, int (*)(const void *, const void *)); - -int abs (int); -long labs (long); -long long llabs (long long); - -typedef struct { int quot, rem; } div_t; -typedef struct { long quot, rem; } ldiv_t; -typedef struct { long long quot, rem; } lldiv_t; - -div_t div (int, int); -ldiv_t ldiv (long, long); -lldiv_t lldiv (long long, long long); - -int mblen (const char *, size_t); -int mbtowc (wchar_t *__restrict, const char *__restrict, size_t); -int wctomb (char *, wchar_t); -size_t mbstowcs (wchar_t *__restrict, const char *__restrict, size_t); -size_t wcstombs (char *__restrict, const wchar_t *__restrict, size_t); - -#define EXIT_FAILURE 1 -#define EXIT_SUCCESS 0 - -#define MB_CUR_MAX ((size_t)+4) - -#define RAND_MAX (0x7fffffff) - - -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ - || defined(_BSD_SOURCE) - -#define WNOHANG 1 -#define WUNTRACED 2 - -#define WEXITSTATUS(s) (((s) & 0xff00) >> 8) -#define WTERMSIG(s) ((s) & 0x7f) -#define WSTOPSIG(s) WEXITSTATUS(s) -#define WIFEXITED(s) (!WTERMSIG(s)) -#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001)>>8) > 0x7f00) -#define WIFSIGNALED(s) (((s)&0xffff)-1U < 0xffu) - -int posix_memalign (void **, size_t, size_t); -int setenv (const char *, const char *, int); -int unsetenv (const char *); -int mkstemp (char *); -int mkostemp (char *, int); -char *mkdtemp (char *); -int getsubopt (char **, char *const *, char **); -int rand_r (unsigned *); - -#endif - - -#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ - || defined(_BSD_SOURCE) -char *realpath (const char *__restrict, char *__restrict); -long int random (void); -void srandom (unsigned int); -char *initstate (unsigned int, char *, size_t); -char *setstate (char *); -#endif - -#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) -int putenv (char *); -int posix_openpt (int); -int grantpt (int); -int unlockpt (int); -char *ptsname (int); -char *l64a (long); -long a64l (const char *); -void setkey (const char *); -double drand48 (void); -double erand48 (unsigned short [3]); -long int lrand48 (void); -long int nrand48 (unsigned short [3]); -long mrand48 (void); -long jrand48 (unsigned short [3]); -void srand48 (long); -unsigned short *seed48 (unsigned short [3]); -void lcong48 (unsigned short [7]); -#endif - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#include -char *mktemp (char *); -int mkstemps (char *, int); -int mkostemps (char *, int, int); -void *valloc (size_t); -void *memalign(size_t, size_t); -int getloadavg(double *, int); -#define WCOREDUMP(s) ((s) & 0x80) -#define WIFCONTINUED(s) ((s) == 0xffff) -#endif - -#ifdef _GNU_SOURCE -int clearenv(void); -int ptsname_r(int, char *, size_t); -char *ecvt(double, int, int *, int *); -char *fcvt(double, int, int *, int *); -char *gcvt(double, int, char *); -struct __locale_struct; -float strtof_l(const char *__restrict, char **__restrict, struct __locale_struct *); -double strtod_l(const char *__restrict, char **__restrict, struct __locale_struct *); -long double strtold_l(const char *__restrict, char **__restrict, struct __locale_struct *); -#endif - -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) -#define mkstemp64 mkstemp -#define mkostemp64 mkostemp -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define mkstemps64 mkstemps -#define mkostemps64 mkostemps -#endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/user/include/string.h b/user/include/string.h deleted file mode 100644 index ff9badb9..00000000 --- a/user/include/string.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef _STRING_H -#define _STRING_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#ifdef __cplusplus -#define NULL 0L -#else -#define NULL ((void*)0) -#endif - -#define __NEED_size_t -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ - || defined(_BSD_SOURCE) -#define __NEED_locale_t -#endif - -#include - -void *memcpy (void *__restrict, const void *__restrict, size_t); -void *memmove (void *, const void *, size_t); -void *memset (void *, int, size_t); -int memcmp (const void *, const void *, size_t); -void *memchr (const void *, int, size_t); - -char *strcpy (char *__restrict, const char *__restrict); -char *strncpy (char *__restrict, const char *__restrict, size_t); - -char *strcat (char *__restrict, const char *__restrict); -char *strncat (char *__restrict, const char *__restrict, size_t); - -int strcmp (const char *, const char *); -int strncmp (const char *, const char *, size_t); - -int strcoll (const char *, const char *); -size_t strxfrm (char *__restrict, const char *__restrict, size_t); - -char *strchr (const char *, int); -char *strrchr (const char *, int); - -size_t strcspn (const char *, const char *); -size_t strspn (const char *, const char *); -char *strpbrk (const char *, const char *); -char *strstr (const char *, const char *); -char *strtok (char *__restrict, const char *__restrict); - -size_t strlen (const char *); - -char *strerror (int); - -#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) -#include -#endif - -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ - || defined(_BSD_SOURCE) -char *strtok_r (char *__restrict, const char *__restrict, char **__restrict); -int strerror_r (int, char *, size_t); -char *stpcpy(char *__restrict, const char *__restrict); -char *stpncpy(char *__restrict, const char *__restrict, size_t); -size_t strnlen (const char *, size_t); -char *strdup (const char *); -char *strndup (const char *, size_t); -char *strsignal(int); -char *strerror_l (int, locale_t); -int strcoll_l (const char *, const char *, locale_t); -size_t strxfrm_l (char *__restrict, const char *__restrict, size_t, locale_t); -#endif - -#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ - || defined(_BSD_SOURCE) -void *memccpy (void *__restrict, const void *__restrict, int, size_t); -#endif - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -char *strsep(char **, const char *); -size_t strlcat (char *, const char *, size_t); -size_t strlcpy (char *, const char *, size_t); -#endif - -#ifdef _GNU_SOURCE -#define strdupa(x) strcpy(alloca(strlen(x)+1),x) -int strverscmp (const char *, const char *); -int strcasecmp_l (const char *, const char *, locale_t); -int strncasecmp_l (const char *, const char *, size_t, locale_t); -char *strchrnul(const char *, int); -char *strcasestr(const char *, const char *); -void *memmem(const void *, size_t, const void *, size_t); -void *memrchr(const void *, int, size_t); -void *mempcpy(void *, const void *, size_t); -#ifndef __cplusplus -char *basename(); -#endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/user/include/sys/ioctl.h b/user/include/sys/ioctl.h deleted file mode 100644 index d0415b3d..00000000 --- a/user/include/sys/ioctl.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _SYS_IOCTL_H -#define _SYS_IOCTL_H -#ifdef __cplusplus -extern "C" { -#endif - -#include - -int ioctl (int, int, ...); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/user/include/sys/uio.h b/user/include/sys/uio.h deleted file mode 100644 index 00f73a2f..00000000 --- a/user/include/sys/uio.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef _SYS_UIO_H -#define _SYS_UIO_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#define __NEED_size_t -#define __NEED_ssize_t -#define __NEED_struct_iovec - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define __NEED_off_t -#endif - -#ifdef _GNU_SOURCE -#define __NEED_pid_t -#endif - -#include - -#define UIO_MAXIOV 1024 - -ssize_t readv (int, const struct iovec *, int); -ssize_t writev (int, const struct iovec *, int); - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -ssize_t preadv (int, const struct iovec *, int, off_t); -ssize_t pwritev (int, const struct iovec *, int, off_t); -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) -#define preadv64 preadv -#define pwritev64 pwritev -#define off64_t off_t -#endif -#endif - -#ifdef _GNU_SOURCE -ssize_t process_vm_writev(pid_t, const struct iovec *, unsigned long, const struct iovec *, unsigned long, unsigned long); -ssize_t process_vm_readv(pid_t, const struct iovec *, unsigned long, const struct iovec *, unsigned long, unsigned long); -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/user/include/termios.h b/user/include/termios.h deleted file mode 100644 index d73c780d..00000000 --- a/user/include/termios.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _TERMIOS_H -#define _TERMIOS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#define __NEED_pid_t - -#include - -typedef unsigned char cc_t; -typedef unsigned int speed_t; -typedef unsigned int tcflag_t; - -#define NCCS 32 - -#include - -speed_t cfgetospeed (const struct termios *); -speed_t cfgetispeed (const struct termios *); -int cfsetospeed (struct termios *, speed_t); -int cfsetispeed (struct termios *, speed_t); - -int tcgetattr (int, struct termios *); -int tcsetattr (int, int, const struct termios *); - -int tcsendbreak (int, int); -int tcdrain (int); -int tcflush (int, int); -int tcflow (int, int); - -pid_t tcgetsid (int); - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -void cfmakeraw(struct termios *); -int cfsetspeed(struct termios *, speed_t); -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/user/include/wchar.h b/user/include/wchar.h deleted file mode 100644 index 9fd967cc..00000000 --- a/user/include/wchar.h +++ /dev/null @@ -1,187 +0,0 @@ -#ifndef _WCHAR_H -#define _WCHAR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#define __NEED_FILE -#define __NEED___isoc_va_list -#define __NEED_size_t -#define __NEED_wchar_t -#define __NEED_wint_t - -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define __NEED_locale_t -#define __NEED_va_list -#endif - -#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define __NEED_wctype_t -#endif - -#include - -#if L'\0'-1 > 0 -#define WCHAR_MAX (0xffffffffu+L'\0') -#define WCHAR_MIN (0+L'\0') -#else -#define WCHAR_MAX (0x7fffffff+L'\0') -#define WCHAR_MIN (-1-0x7fffffff+L'\0') -#endif - -#ifdef __cplusplus -#define NULL 0L -#else -#define NULL ((void*)0) -#endif - -#undef WEOF -#define WEOF 0xffffffffU - -typedef struct __mbstate_t -{ - unsigned __opaque1, __opaque2; -} mbstate_t; - -wchar_t *wcscpy (wchar_t *__restrict, const wchar_t *__restrict); -wchar_t *wcsncpy (wchar_t *__restrict, const wchar_t *__restrict, size_t); - -wchar_t *wcscat (wchar_t *__restrict, const wchar_t *__restrict); -wchar_t *wcsncat (wchar_t *__restrict, const wchar_t *__restrict, size_t); - -int wcscmp (const wchar_t *, const wchar_t *); -int wcsncmp (const wchar_t *, const wchar_t *, size_t); - -int wcscoll(const wchar_t *, const wchar_t *); -size_t wcsxfrm (wchar_t *__restrict, const wchar_t *__restrict, size_t n); - -wchar_t *wcschr (const wchar_t *, wchar_t); -wchar_t *wcsrchr (const wchar_t *, wchar_t); - -size_t wcscspn (const wchar_t *, const wchar_t *); -size_t wcsspn (const wchar_t *, const wchar_t *); -wchar_t *wcspbrk (const wchar_t *, const wchar_t *); - -wchar_t *wcstok (wchar_t *__restrict, const wchar_t *__restrict, wchar_t **__restrict); - -size_t wcslen (const wchar_t *); - -wchar_t *wcsstr (const wchar_t *__restrict, const wchar_t *__restrict); -wchar_t *wcswcs (const wchar_t *, const wchar_t *); - -wchar_t *wmemchr (const wchar_t *, wchar_t, size_t); -int wmemcmp (const wchar_t *, const wchar_t *, size_t); -wchar_t *wmemcpy (wchar_t *__restrict, const wchar_t *__restrict, size_t); -wchar_t *wmemmove (wchar_t *, const wchar_t *, size_t); -wchar_t *wmemset (wchar_t *, wchar_t, size_t); - -wint_t btowc (int); -int wctob (wint_t); - -int mbsinit (const mbstate_t *); -size_t mbrtowc (wchar_t *__restrict, const char *__restrict, size_t, mbstate_t *__restrict); -size_t wcrtomb (char *__restrict, wchar_t, mbstate_t *__restrict); - -size_t mbrlen (const char *__restrict, size_t, mbstate_t *__restrict); - -size_t mbsrtowcs (wchar_t *__restrict, const char **__restrict, size_t, mbstate_t *__restrict); -size_t wcsrtombs (char *__restrict, const wchar_t **__restrict, size_t, mbstate_t *__restrict); - -float wcstof (const wchar_t *__restrict, wchar_t **__restrict); -double wcstod (const wchar_t *__restrict, wchar_t **__restrict); -long double wcstold (const wchar_t *__restrict, wchar_t **__restrict); - -long wcstol (const wchar_t *__restrict, wchar_t **__restrict, int); -unsigned long wcstoul (const wchar_t *__restrict, wchar_t **__restrict, int); - -long long wcstoll (const wchar_t *__restrict, wchar_t **__restrict, int); -unsigned long long wcstoull (const wchar_t *__restrict, wchar_t **__restrict, int); - - - -int fwide (FILE *, int); - - -int wprintf (const wchar_t *__restrict, ...); -int fwprintf (FILE *__restrict, const wchar_t *__restrict, ...); -int swprintf (wchar_t *__restrict, size_t, const wchar_t *__restrict, ...); - -int vwprintf (const wchar_t *__restrict, __isoc_va_list); -int vfwprintf (FILE *__restrict, const wchar_t *__restrict, __isoc_va_list); -int vswprintf (wchar_t *__restrict, size_t, const wchar_t *__restrict, __isoc_va_list); - -int wscanf (const wchar_t *__restrict, ...); -int fwscanf (FILE *__restrict, const wchar_t *__restrict, ...); -int swscanf (const wchar_t *__restrict, const wchar_t *__restrict, ...); - -int vwscanf (const wchar_t *__restrict, __isoc_va_list); -int vfwscanf (FILE *__restrict, const wchar_t *__restrict, __isoc_va_list); -int vswscanf (const wchar_t *__restrict, const wchar_t *__restrict, __isoc_va_list); - -wint_t fgetwc (FILE *); -wint_t getwc (FILE *); -wint_t getwchar (void); - -wint_t fputwc (wchar_t, FILE *); -wint_t putwc (wchar_t, FILE *); -wint_t putwchar (wchar_t); - -wchar_t *fgetws (wchar_t *__restrict, int, FILE *__restrict); -int fputws (const wchar_t *__restrict, FILE *__restrict); - -wint_t ungetwc (wint_t, FILE *); - -struct tm; -size_t wcsftime (wchar_t *__restrict, size_t, const wchar_t *__restrict, const struct tm *__restrict); - -#undef iswdigit - -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -FILE *open_wmemstream(wchar_t **, size_t *); -size_t mbsnrtowcs(wchar_t *__restrict, const char **__restrict, size_t, size_t, mbstate_t *__restrict); -size_t wcsnrtombs(char *__restrict, const wchar_t **__restrict, size_t, size_t, mbstate_t *__restrict); -wchar_t *wcsdup(const wchar_t *); -size_t wcsnlen (const wchar_t *, size_t); -wchar_t *wcpcpy (wchar_t *__restrict, const wchar_t *__restrict); -wchar_t *wcpncpy (wchar_t *__restrict, const wchar_t *__restrict, size_t); -int wcscasecmp(const wchar_t *, const wchar_t *); -int wcscasecmp_l(const wchar_t *, const wchar_t *, locale_t); -int wcsncasecmp(const wchar_t *, const wchar_t *, size_t); -int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t, locale_t); -int wcscoll_l(const wchar_t *, const wchar_t *, locale_t); -size_t wcsxfrm_l(wchar_t *__restrict, const wchar_t *__restrict, size_t n, locale_t); -#endif - -#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -int wcwidth (wchar_t); -int wcswidth (const wchar_t *, size_t); -int iswalnum(wint_t); -int iswalpha(wint_t); -int iswblank(wint_t); -int iswcntrl(wint_t); -int iswdigit(wint_t); -int iswgraph(wint_t); -int iswlower(wint_t); -int iswprint(wint_t); -int iswpunct(wint_t); -int iswspace(wint_t); -int iswupper(wint_t); -int iswxdigit(wint_t); -int iswctype(wint_t, wctype_t); -wint_t towlower(wint_t); -wint_t towupper(wint_t); -wctype_t wctype(const char *); -#undef iswdigit -#define iswdigit(a) ((unsigned)(a)-'0' < 10) -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/user/infinite_hello/infinite_hello.c b/user/infinite_hello/infinite_hello.c new file mode 100644 index 00000000..ac50692f --- /dev/null +++ b/user/infinite_hello/infinite_hello.c @@ -0,0 +1,5 @@ +#include + +int main() { + for(;;) printf("Hello, World!\n"); +} diff --git a/user/lib/crt1.o b/user/lib/crt1.o deleted file mode 100644 index fd77619e..00000000 Binary files a/user/lib/crt1.o and /dev/null differ diff --git a/user/lib/crti.o b/user/lib/crti.o deleted file mode 100644 index 97ed3bce..00000000 Binary files a/user/lib/crti.o and /dev/null differ diff --git a/user/lib/crtn.o b/user/lib/crtn.o deleted file mode 100644 index f3f42434..00000000 Binary files a/user/lib/crtn.o and /dev/null differ diff --git a/user/libc/Makefile b/user/libc/Makefile deleted file mode 100644 index 9808ddaf..00000000 --- a/user/libc/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -include $(CURDIR)/../../config.mk - -TOOLCHAIN_PATH:=$(CURDIR)/../../$(TOOLCHAIN_DIR)/$(BARE_METAL_TARGET)/bin -CC:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-gcc -AR:=$(TOOLCHAIN_PATH)/$(BARE_METAL_TUPLE)-ar - -OBJS=stdio/printf.o \ - stdio/vfprintf.o \ - stdio/fwrite.o \ - stdio/stdout.o \ - stdio/__stdio_write.o \ - stdio/__stdio_seek.o \ - stdio/__stdio_close.o \ - stdio/__stdio_exit.o \ - stdio/__stdout_write.o \ - stdio/__towrite.o \ - stdio/__lockfile.o \ - string/memcpy.o \ - string/memset.o \ - string/memchr.o \ - errno/__errno_location.o \ - errno/strerror.o \ - math/frexpl.o \ - math/frexp.o \ - multibyte/wctob.o \ - multibyte/wctomb.o \ - multibyte/wcrtomb.o \ - internal/syscall.o \ - internal/syscall_ret.o \ - internal/libc.o \ - dummy/dummy.o \ - env/__libc_start_main.o \ - env/__environ.o \ - malloc/malloc_syscalls.o \ - exit/exit.o \ - exit/_Exit.o \ - file_system/fs_syscalls.o - -CFLAGS += -Os -pipe -CFLAGS += -std=c99 -ffreestanding -nostdinc -CFLAGS += -D_XOPEN_SOURCE=700 - -all: libc.a - -libc.a: $(OBJS) - $(AR) rcs libc.a $(OBJS) - -%.o: %.c - $(CC) $(CFLAGS) -Iarch/arm -Iinternal -I../include -c $< -o $@ - -%.o: %.s - $(CC) $(CFLAGS) -Iarch/arm -Iinternal -I../include -c $< -o $@ - -clean: - rm -f stdio/*.o - rm -f string/*.o - rm -f errno/*.o - rm -f math/*.o - rm -f multibyte/*.o - rm -f internal/*.o - rm -f dummy/*.o - rm -f env/*.o - rm -f exit/*.o - rm -f libc.a diff --git a/user/libc/arch/arm/syscall_arch.h b/user/libc/arch/arm/syscall_arch.h deleted file mode 100644 index e10748a4..00000000 --- a/user/libc/arch/arm/syscall_arch.h +++ /dev/null @@ -1,94 +0,0 @@ -#define __SYSCALL_LL_E(x) \ -((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ -((union { long long ll; long l[2]; }){ .ll = x }).l[1] -#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x)) - -long (__syscall)(long, ...); - -#ifndef __clang__ - -#define __asm_syscall(...) do { \ - __asm__ __volatile__ ( "svc 0" \ - : "=r"(r0) : __VA_ARGS__ : "memory"); \ - return r0; \ - } while (0) - -static inline long __syscall0(long n) -{ - register long r7 __asm__("r7") = n; - register long r0 __asm__("r0"); - __asm_syscall("r"(r7)); -} - -static inline long __syscall1(long n, long a) -{ - register long r7 __asm__("r7") = n; - register long r0 __asm__("r0") = a; - __asm_syscall("r"(r7), "0"(r0)); -} - -static inline long __syscall2(long n, long a, long b) -{ - register long r7 __asm__("r7") = n; - register long r0 __asm__("r0") = a; - register long r1 __asm__("r1") = b; - __asm_syscall("r"(r7), "0"(r0), "r"(r1)); -} - -static inline long __syscall3(long n, long a, long b, long c) -{ - register long r7 __asm__("r7") = n; - register long r0 __asm__("r0") = a; - register long r1 __asm__("r1") = b; - register long r2 __asm__("r2") = c; - __asm_syscall("r"(r7), "0"(r0), "r"(r1), "r"(r2)); -} - -static inline long __syscall4(long n, long a, long b, long c, long d) -{ - register long r7 __asm__("r7") = n; - register long r0 __asm__("r0") = a; - register long r1 __asm__("r1") = b; - register long r2 __asm__("r2") = c; - register long r3 __asm__("r3") = d; - __asm_syscall("r"(r7), "0"(r0), "r"(r1), "r"(r2), "r"(r3)); -} - -#else - -static inline long __syscall0(long n) -{ - return (__syscall)(n); -} - -static inline long __syscall1(long n, long a) -{ - return (__syscall)(n, a); -} - -static inline long __syscall2(long n, long a, long b) -{ - return (__syscall)(n, a, b); -} - -static inline long __syscall3(long n, long a, long b, long c) -{ - return (__syscall)(n, a, b, c); -} - -static inline long __syscall4(long n, long a, long b, long c, long d) -{ - return (__syscall)(n, a, b, c, d); -} - -#endif - -static inline long __syscall5(long n, long a, long b, long c, long d, long e) -{ - return (__syscall)(n, a, b, c, d, e); -} - -static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) -{ - return (__syscall)(n, a, b, c, d, e, f); -} diff --git a/user/libc/dummy/dummy.c b/user/libc/dummy/dummy.c deleted file mode 100644 index bffd4f47..00000000 --- a/user/libc/dummy/dummy.c +++ /dev/null @@ -1,5 +0,0 @@ -void __lock(volatile int *l) -{ - -} - diff --git a/user/libc/env/__environ.c b/user/libc/env/__environ.c deleted file mode 100644 index e6c6faa5..00000000 --- a/user/libc/env/__environ.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "libc.h" - -char **__environ = 0; -weak_alias(__environ, ___environ); -weak_alias(__environ, _environ); -weak_alias(__environ, environ); diff --git a/user/libc/env/__libc_start_main.c b/user/libc/env/__libc_start_main.c deleted file mode 100644 index ac77e18b..00000000 --- a/user/libc/env/__libc_start_main.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include "libc.h" - -void __init_tls(size_t *); -void __init_security(size_t *); -void __init_ldso_ctors(void); - -#ifndef SHARED -static void dummy() {} -weak_alias(dummy, _init); -extern void (*const __init_array_start)() __attribute__((weak)); -extern void (*const __init_array_end)() __attribute__((weak)); -#endif - -#define AUX_CNT 38 - -extern size_t __hwcap, __sysinfo; -extern char *__progname, *__progname_full; - -void __init_libc(char **envp, char *pn) -{ - size_t i, *auxv, aux[AUX_CNT] = { 0 }; - __environ = envp; - for (i=0; envp[i]; i++); - libc.auxv = auxv = (void *)(envp+i+1); - for (i=0; auxv[i]; i+=2) if (auxv[i]errno_ptr; - return &e; -} diff --git a/user/libc/errno/__strerror.h b/user/libc/errno/__strerror.h deleted file mode 100644 index 915044b5..00000000 --- a/user/libc/errno/__strerror.h +++ /dev/null @@ -1,104 +0,0 @@ -/* This file is sorted such that 'errors' which represent exceptional - * conditions under which a correct program may fail come first, followed - * by messages that indicate an incorrect program or system failure. The - * macro E() along with double-inclusion is used to ensure that ordering - * of the strings remains synchronized. */ - -E(EILSEQ, "Illegal byte sequence") -E(EDOM, "Domain error") -E(ERANGE, "Result not representable") - -E(ENOTTY, "Not a tty") -E(EACCES, "Permission denied") -E(EPERM, "Operation not permitted") -E(ENOENT, "No such file or directory") -E(ESRCH, "No such process") -E(EEXIST, "File exists") - -E(EOVERFLOW, "Value too large for data type") -E(ENOSPC, "No space left on device") -E(ENOMEM, "Out of memory") - -E(EBUSY, "Resource busy") -E(EINTR, "Interrupted system call") -E(EAGAIN, "Resource temporarily unavailable") -E(ESPIPE, "Invalid seek") - -E(EXDEV, "Cross-device link") -E(EROFS, "Read-only file system") -E(ENOTEMPTY, "Directory not empty") - -E(ECONNRESET, "Connection reset by peer") -E(ETIMEDOUT, "Operation timed out") -E(ECONNREFUSED, "Connection refused") -E(EHOSTDOWN, "Host is down") -E(EHOSTUNREACH, "Host is unreachable") -E(EADDRINUSE, "Address in use") - -E(EPIPE, "Broken pipe") -E(EIO, "I/O error") -E(ENXIO, "No such device or address") -E(ENOTBLK, "Block device required") -E(ENODEV, "No such device") -E(ENOTDIR, "Not a directory") -E(EISDIR, "Is a directory") -E(ETXTBSY, "Text file busy") -E(ENOEXEC, "Exec format error") - -E(EINVAL, "Invalid argument") - -E(E2BIG, "Argument list too long") -E(ELOOP, "Symbolic link loop") -E(ENAMETOOLONG, "Filename too long") -E(ENFILE, "Too many open files in system") -E(EMFILE, "No file descriptors available") -E(EBADF, "Bad file descriptor") -E(ECHILD, "No child process") -E(EFAULT, "Bad address") -E(EFBIG, "File too large") -E(EMLINK, "Too many links") -E(ENOLCK, "No locks available") - -E(EDEADLK, "Resource deadlock would occur") -E(ENOTRECOVERABLE, "State not recoverable") -E(EOWNERDEAD, "Previous owner died") -E(ECANCELED, "Operation canceled") -E(ENOSYS, "Function not implemented") -E(ENOMSG, "No message of desired type") -E(EIDRM, "Identifier removed") -E(ENOSTR, "Device not a stream") -E(ENODATA, "No data available") -E(ETIME, "Device timeout") -E(ENOSR, "Out of streams resources") -E(ENOLINK, "Link has been severed") -E(EPROTO, "Protocol error") -E(EBADMSG, "Bad message") -E(EBADFD, "File descriptor in bad state") -E(ENOTSOCK, "Not a socket") -E(EDESTADDRREQ, "Destination address required") -E(EMSGSIZE, "Message too large") -E(EPROTOTYPE, "Protocol wrong type for socket") -E(ENOPROTOOPT, "Protocol not available") -E(EPROTONOSUPPORT,"Protocol not supported") -E(ESOCKTNOSUPPORT,"Socket type not supported") -E(ENOTSUP, "Not supported") -E(EPFNOSUPPORT, "Protocol family not supported") -E(EAFNOSUPPORT, "Address family not supported by protocol") -E(EADDRNOTAVAIL,"Address not available") -E(ENETDOWN, "Network is down") -E(ENETUNREACH, "Network unreachable") -E(ENETRESET, "Connection reset by network") -E(ECONNABORTED, "Connection aborted") -E(ENOBUFS, "No buffer space available") -E(EISCONN, "Socket is connected") -E(ENOTCONN, "Socket not connected") -E(ESHUTDOWN, "Cannot send after socket shutdown") -E(EALREADY, "Operation already in progress") -E(EINPROGRESS, "Operation in progress") -E(ESTALE, "Stale file handle") -E(EREMOTEIO, "Remote I/O error") -E(EDQUOT, "Quota exceeded") -E(ENOMEDIUM, "No medium found") -E(EMEDIUMTYPE, "Wrong medium type") - -E(0, "No error information") diff --git a/user/libc/errno/strerror.c b/user/libc/errno/strerror.c deleted file mode 100644 index b5559cbe..00000000 --- a/user/libc/errno/strerror.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include - -#define E(a,b) ((unsigned char)a), -static const unsigned char errid[] = { -#include "__strerror.h" -}; - -#undef E -#define E(a,b) b "\0" -static const char errmsg[] = -#include "__strerror.h" -; - -char *strerror(int e) -{ - const char *s; - int i; - /* mips has one error code outside of the 8-bit range due to a - * historical typo, so we just remap it. */ - if (EDQUOT==1133) { - if (e==109) e=-1; - else if (e==EDQUOT) e=109; - } - for (i=0; errid[i] && errid[i] != e; i++); - for (s=errmsg; i; s++, i--) for (; *s; s++); - return (char *)s; -} diff --git a/user/libc/exit/_Exit.c b/user/libc/exit/_Exit.c deleted file mode 100644 index b51cd92c..00000000 --- a/user/libc/exit/_Exit.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include "syscall.h" - -#define SYS_exit 100 - -_Noreturn void _Exit(int ec) -{ - //__syscall(SYS_exit_group, ec); - //for (;;) __syscall(SYS_exit, ec); - for (;;) __syscall(SYS_exit, ec); -} diff --git a/user/libc/exit/exit.c b/user/libc/exit/exit.c deleted file mode 100644 index acb3462a..00000000 --- a/user/libc/exit/exit.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include -#include "libc.h" -#include "atomic.h" -#include "syscall.h" - -static void dummy() -{ -} - -/* __toread.c, __towrite.c, and atexit.c override these */ -weak_alias(dummy, __funcs_on_exit); -weak_alias(dummy, __flush_on_exit); -weak_alias(dummy, __seek_on_exit); - -#ifndef SHARED -weak_alias(dummy, _fini); -extern void (*const __fini_array_start)() __attribute__((weak)); -extern void (*const __fini_array_end)() __attribute__((weak)); -#endif - -#define SYS_pause 102 - -_Noreturn void exit(int code) -{ - static int lock; - - /* If more than one thread calls exit, hang until _Exit ends it all */ - while (a_swap(&lock, 1)) __syscall(SYS_pause); - - __funcs_on_exit(); - -#ifndef SHARED - uintptr_t a = (uintptr_t)&__fini_array_end; - for (; a>(uintptr_t)&__fini_array_start; a-=sizeof(void(*)())) - (*(void (**)())(a-sizeof(void(*)())))(); - _fini(); -#endif - - __flush_on_exit(); - __seek_on_exit(); - - _Exit(code); - for(;;); -} diff --git a/user/libc/file_system/fs_syscalls.c b/user/libc/file_system/fs_syscalls.c deleted file mode 100644 index 06a169ae..00000000 --- a/user/libc/file_system/fs_syscalls.c +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include "../../include/fs_syscalls.h" -#include "../arch/arm/syscall_arch.h" - -/* open() returns a file descriptor, a long used to call later fuctions. -A return value of -1 tells that an error occurred and the file cannot be opened */ -int open(char* filepath, char mode){ - if(mode != 'r' && mode != 'w' && mode != 'a' && mode!='b'){ - - //os_printf("mode is not a valid option. \n"); - //os_printf("r=read, w=write, b=both read and write, a=append.\n"); - return -1; - } - - /* move filepath and mode into registers r0 and r1, call SYSCALL_OPEN */ - long fd = __syscall2(SYSCALL_OPEN, (long)filepath, (long)mode); - - return (int) fd; -}//end open syscall - -/* create() returns a file descriptor to use in later functions */ -int create(char* filepath, char mode){ - - if(mode != 'r' && mode != 'w' && mode != 'a' && mode!='b'){ - - //os_printf("mode is not a valid option. \n"); - //os_printf("r=read, w=write, b=both read and write, a=append.\n"); - return -1; - } - - /* move filepath and mode into registers r0 and r1, call SYSCALL_MKDIR */ - long error = __syscall2(SYSCALL_CREATE, (long)filepath, (long)mode); - - return (int)error; -}//end create syscall - -//creates a directory -int mkdir(char* filepath) { - long error = __syscall1(SYSCALL_MKDIR, (long)filepath); - return (int)error; -} - -/* read() returns the amount of bytes successfully read from the file */ -int read(int fd, void* buf, int numBytes){ - - if (numBytes<=0) { return -1; }//os_printf("Invalid number of bytes \n"); } */ - - /* move fd, buf, and numBytes into r0, r1, r2 and call SYSCALL_READ */ - long bytesRead = __syscall3(SYSCALL_READ, (long)fd, (long)buf, (long)numBytes); - - return (int)bytesRead; -}//end open syscall - -/*write() returns the number of bytes that were actually written*/ -int write(int fd, void* buf, int numBytes){ - - if (numBytes<=0){ - //os_printf("Invalid number of bytes\n"); - return -1; - } - - /* move fd, buf, and numBytes into r0, r1, r2 and call SYSCALL_WRITE */ - long bytesWritten = __syscall3(SYSCALL_READ, (long)fd, (long)buf, (long)numBytes); - - return (int)bytesWritten; -}//end write syscall - -/* close() returns the 0 if successful and -1 if not */ -int close(int fd){ - - /* move fd to r0 and call SYSCALL_CLOSE */ - long error = __syscall1(SYSCALL_CLOSE, (long)fd); - - return (int)error; -}//end close syscall - -/* seek() returns the number of bytes that the file offset is successfully moved - if successful, and -1 if the numBytes puts puts them outside the file length */ -int seek(int fd, int numBytes){ - - if(numBytes == 0){ - return 0; - } - - /* move fd, numBytes into registers r0, r1 and call SYSCALL_SEEK */ - long error = __syscall2(SYSCALL_SEEK, (long) fd, (long) numBytes); - - return (int)error; -}//end seek syscall - -/* delete() returns the 0 if successful and -1 if not */ -int delete(char* filepath){ - - /* move filepath to r0 and call SYSCALL_DELETE */ - long error = __syscall1(SYSCALL_DELETE, (long) filepath); - - return (int)error; -}//end delete syscall - -//copies contents of a file -int copy(char* source, char* dest, char mode) { - if (mode != '0' && mode != 'r' && mode != 'w') { - //os_printf("Enter mode of new file as r for read only or w for write, or 0 if copying a directory \n"); - return -1; - } - long error = __syscall3(SYSCALL_COPY, (long)source, (long) dest, (long) mode); - return (int)error; -} - -//lists elements in a directory -int ls(char* filepath) { - if (filepath == 0x0) { - //os_printf("enter a path! \n"); - return -1; - } - long error = __syscall1(SYSCALL_LS, (long)filepath); - return (int)error; -} - diff --git a/user/libc/internal/atomic.h b/user/libc/internal/atomic.h deleted file mode 100644 index 734d2871..00000000 --- a/user/libc/internal/atomic.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef _INTERNAL_ATOMIC_H -#define _INTERNAL_ATOMIC_H - -#include - -static inline int a_ctz_l(unsigned long x) -{ - static const char debruijn32[32] = { - 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, - 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14 - }; - return debruijn32[(x&-x)*0x076be629 >> 27]; -} - -static inline int a_ctz_64(uint64_t x) -{ - uint32_t y = x; - if (!y) { - y = x>>32; - return 32 + a_ctz_l(y); - } - return a_ctz_l(y); -} - -#define __k_cas ((int (*)(int, int, volatile int *))0xffff0fc0) - -static inline int a_cas(volatile int *p, int t, int s) -{ - int old; - for (;;) { - if (!__k_cas(t, s, p)) - return t; - if ((old=*p) != t) - return old; - } -} - -static inline void *a_cas_p(volatile void *p, void *t, void *s) -{ - return (void *)a_cas(p, (int)t, (int)s); -} - -static inline long a_cas_l(volatile void *p, long t, long s) -{ - return a_cas(p, t, s); -} - -static inline int a_swap(volatile int *x, int v) -{ - int old; - do old = *x; - while (__k_cas(old, v, x)); - return old; -} - -static inline int a_fetch_add(volatile int *x, int v) -{ - int old; - do old = *x; - while (__k_cas(old, old+v, x)); - return old; -} - -static inline void a_inc(volatile int *x) -{ - a_fetch_add(x, 1); -} - -static inline void a_dec(volatile int *x) -{ - a_fetch_add(x, -1); -} - -static inline void a_store(volatile int *p, int x) -{ - while (__k_cas(*p, x, p)); -} - -static inline void a_spin() -{ -} - -static inline void a_crash() -{ - *(volatile char *)0=0; -} - -static inline void a_and(volatile int *p, int v) -{ - int old; - do old = *p; - while (__k_cas(old, old&v, p)); -} - -static inline void a_or(volatile int *p, int v) -{ - int old; - do old = *p; - while (__k_cas(old, old|v, p)); -} - -static inline void a_or_l(volatile void *p, long v) -{ - a_or(p, v); -} - -static inline void a_and_64(volatile uint64_t *p, uint64_t v) -{ - union { uint64_t v; uint32_t r[2]; } u = { v }; - a_and((int *)p, u.r[0]); - a_and((int *)p+1, u.r[1]); -} - -static inline void a_or_64(volatile uint64_t *p, uint64_t v) -{ - union { uint64_t v; uint32_t r[2]; } u = { v }; - a_or((int *)p, u.r[0]); - a_or((int *)p+1, u.r[1]); -} - -#endif diff --git a/user/libc/internal/libc.c b/user/libc/internal/libc.c deleted file mode 100644 index 942f6b44..00000000 --- a/user/libc/internal/libc.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "libc.h" - -#ifdef USE_LIBC_ACCESSOR -struct __libc *__libc_loc() -{ - static struct __libc __libc; - return &__libc; -} -#else -struct __libc __libc; -#endif - -#ifdef BROKEN_VISIBILITY -__asm__(".hidden __libc"); -#endif - -size_t __hwcap; -size_t __sysinfo; -char *__progname=0, *__progname_full=0; - -weak_alias(__progname, program_invocation_short_name); -weak_alias(__progname_full, program_invocation_name); diff --git a/user/libc/internal/libc.h b/user/libc/internal/libc.h deleted file mode 100644 index d625b56a..00000000 --- a/user/libc/internal/libc.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef LIBC_H -#define LIBC_H - -#include -#include -#include - -struct __libc { - void *main_thread; - int threaded; - int secure; - size_t *auxv; - volatile int threads_minus_1; - int canceldisable; - FILE *ofl_head; - int ofl_lock[2]; - size_t tls_size; - size_t page_size; -}; - -extern size_t __hwcap; - -#ifndef PAGE_SIZE -#define PAGE_SIZE libc.page_size -#endif - -#if !defined(__PIC__) || (100*__GNUC__+__GNUC_MINOR__ >= 303 && !defined(__PCC__)) - -#ifdef __PIC__ -#if __GNUC__ < 4 -#define BROKEN_VISIBILITY 1 -#endif -#define ATTR_LIBC_VISIBILITY __attribute__((visibility("hidden"))) -#else -#define ATTR_LIBC_VISIBILITY -#endif - -extern struct __libc __libc ATTR_LIBC_VISIBILITY; -#define libc __libc - -#else - -#define USE_LIBC_ACCESSOR -#define ATTR_LIBC_VISIBILITY -extern struct __libc *__libc_loc(void) __attribute__((const)); -#define libc (*__libc_loc()) - -#endif - - -/* Designed to avoid any overhead in non-threaded processes */ -void __lock(volatile int *) ATTR_LIBC_VISIBILITY; -void __unlock(volatile int *) ATTR_LIBC_VISIBILITY; -int __lockfile(FILE *) ATTR_LIBC_VISIBILITY; -void __unlockfile(FILE *) ATTR_LIBC_VISIBILITY; -#define LOCK(x) __lock(x) -#define UNLOCK(x) __unlock(x) - -void __synccall(void (*)(void *), void *); -int __setxid(int, int, int, int); - -extern char **__environ; - -#undef weak_alias -#define weak_alias(old, new) \ - extern __typeof(old) new __attribute__((weak, alias(#old))) - -#undef LFS64_2 -#define LFS64_2(x, y) weak_alias(x, y) - -#undef LFS64 -#define LFS64(x) LFS64_2(x, x##64) - -#endif diff --git a/user/libc/internal/libm.h b/user/libc/internal/libm.h deleted file mode 100644 index ebcd7849..00000000 --- a/user/libc/internal/libm.h +++ /dev/null @@ -1,158 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/math_private.h */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#ifndef _LIBM_H -#define _LIBM_H - -#include -#include -#include -#include -#include - -#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 -#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN -union ldshape { - long double f; - struct { - uint64_t m; - uint16_t se; - } i; -}; -#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN -union ldshape { - long double f; - struct { - uint64_t lo; - uint32_t mid; - uint16_t top; - uint16_t se; - } i; - struct { - uint64_t lo; - uint64_t hi; - } i2; -}; -#else -#error Unsupported long double representation -#endif - -#define FORCE_EVAL(x) do { \ - if (sizeof(x) == sizeof(float)) { \ - volatile float __x; \ - __x = (x); \ - } else if (sizeof(x) == sizeof(double)) { \ - volatile double __x; \ - __x = (x); \ - } else { \ - volatile long double __x; \ - __x = (x); \ - } \ -} while(0) - -/* Get two 32 bit ints from a double. */ -#define EXTRACT_WORDS(hi,lo,d) \ -do { \ - union {double f; uint64_t i;} __u; \ - __u.f = (d); \ - (hi) = __u.i >> 32; \ - (lo) = (uint32_t)__u.i; \ -} while (0) - -/* Get the more significant 32 bit int from a double. */ -#define GET_HIGH_WORD(hi,d) \ -do { \ - union {double f; uint64_t i;} __u; \ - __u.f = (d); \ - (hi) = __u.i >> 32; \ -} while (0) - -/* Get the less significant 32 bit int from a double. */ -#define GET_LOW_WORD(lo,d) \ -do { \ - union {double f; uint64_t i;} __u; \ - __u.f = (d); \ - (lo) = (uint32_t)__u.i; \ -} while (0) - -/* Set a double from two 32 bit ints. */ -#define INSERT_WORDS(d,hi,lo) \ -do { \ - union {double f; uint64_t i;} __u; \ - __u.i = ((uint64_t)(hi)<<32) | (uint32_t)(lo); \ - (d) = __u.f; \ -} while (0) - -/* Set the more significant 32 bits of a double from an int. */ -#define SET_HIGH_WORD(d,hi) \ -do { \ - union {double f; uint64_t i;} __u; \ - __u.f = (d); \ - __u.i &= 0xffffffff; \ - __u.i |= (uint64_t)(hi) << 32; \ - (d) = __u.f; \ -} while (0) - -/* Set the less significant 32 bits of a double from an int. */ -#define SET_LOW_WORD(d,lo) \ -do { \ - union {double f; uint64_t i;} __u; \ - __u.f = (d); \ - __u.i &= 0xffffffff00000000ull; \ - __u.i |= (uint32_t)(lo); \ - (d) = __u.f; \ -} while (0) - -/* Get a 32 bit int from a float. */ -#define GET_FLOAT_WORD(w,d) \ -do { \ - union {float f; uint32_t i;} __u; \ - __u.f = (d); \ - (w) = __u.i; \ -} while (0) - -/* Set a float from a 32 bit int. */ -#define SET_FLOAT_WORD(d,w) \ -do { \ - union {float f; uint32_t i;} __u; \ - __u.i = (w); \ - (d) = __u.f; \ -} while (0) - -/* fdlibm kernel functions */ - -int __rem_pio2_large(double*,double*,int,int,int); - -int __rem_pio2(double,double*); -double __sin(double,double,int); -double __cos(double,double); -double __tan(double,double,int); -double __expo2(double); -double complex __ldexp_cexp(double complex,int); - -int __rem_pio2f(float,double*); -float __sindf(double); -float __cosdf(double); -float __tandf(double,int); -float __expo2f(float); -float complex __ldexp_cexpf(float complex,int); - -int __rem_pio2l(long double, long double *); -long double __sinl(long double, long double, int); -long double __cosl(long double, long double); -long double __tanl(long double, long double, int); - -/* polynomial evaluation */ -long double __polevll(long double, const long double *, int); -long double __p1evll(long double, const long double *, int); - -#endif diff --git a/user/libc/internal/stdio_impl.h b/user/libc/internal/stdio_impl.h deleted file mode 100644 index d2c3b4e8..00000000 --- a/user/libc/internal/stdio_impl.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef _STDIO_IMPL_H -#define _STDIO_IMPL_H - -#define __NEED_off_t - -#include -#include "syscall.h" -#include "libc.h" - -#define UNGET 8 - -#define FFINALLOCK(f) ((f)->lock>=0 ? __lockfile((f)) : 0) -#define FLOCK(f) int __need_unlock = ((f)->lock>=0 ? __lockfile((f)) : 0) -#define FUNLOCK(f) if (__need_unlock) __unlockfile((f)); else - -#define F_PERM 1 -#define F_NORD 4 -#define F_NOWR 8 -#define F_EOF 16 -#define F_ERR 32 -#define F_SVB 64 -#define F_APP 128 - -struct _IO_FILE { - unsigned flags; - unsigned char *rpos, *rend; - int (*close)(FILE *); - unsigned char *wend, *wpos; - unsigned char *mustbezero_1; - unsigned char *wbase; - size_t (*read)(FILE *, unsigned char *, size_t); - size_t (*write)(FILE *, const unsigned char *, size_t); - off_t (*seek)(FILE *, off_t, int); - unsigned char *buf; - size_t buf_size; - FILE *prev, *next; - int fd; - int pipe_pid; - long lockcount; - short dummy3; - signed char mode; - signed char lbf; - int lock; - int waiters; - void *cookie; - off_t off; - char *getln_buf; - void *mustbezero_2; - unsigned char *shend; - off_t shlim, shcnt; -}; - -size_t __stdio_read(FILE *, unsigned char *, size_t); -size_t __stdio_write(FILE *, const unsigned char *, size_t); -size_t __stdout_write(FILE *, const unsigned char *, size_t); -off_t __stdio_seek(FILE *, off_t, int); -int __stdio_close(FILE *); - -size_t __string_read(FILE *, unsigned char *, size_t); - -int __toread(FILE *); -int __towrite(FILE *); - -#if defined(__PIC__) && (100*__GNUC__+__GNUC_MINOR__ >= 303) -__attribute__((visibility("protected"))) -#endif -int __overflow(FILE *, int), __uflow(FILE *); - -int __fseeko(FILE *, off_t, int); -int __fseeko_unlocked(FILE *, off_t, int); -off_t __ftello(FILE *); -off_t __ftello_unlocked(FILE *); -size_t __fwritex(const unsigned char *, size_t, FILE *); -int __putc_unlocked(int, FILE *); - -FILE *__fdopen(int, const char *); -int __fmodeflags(const char *); - -#define OFLLOCK() LOCK(libc.ofl_lock) -#define OFLUNLOCK() UNLOCK(libc.ofl_lock) - -#define feof(f) ((f)->flags & F_EOF) -#define ferror(f) ((f)->flags & F_ERR) - -#define getc_unlocked(f) \ - ( ((f)->rpos < (f)->rend) ? *(f)->rpos++ : __uflow((f)) ) - -#define putc_unlocked(c, f) ( ((c)!=(f)->lbf && (f)->wpos<(f)->wend) \ - ? *(f)->wpos++ = (c) : __overflow((f),(c)) ) - -/* Caller-allocated FILE * operations */ -FILE *__fopen_rb_ca(const char *, FILE *, unsigned char *, size_t); -int __fclose_ca(FILE *); - -#endif diff --git a/user/libc/internal/syscall.h b/user/libc/internal/syscall.h deleted file mode 100644 index 9e3d812c..00000000 --- a/user/libc/internal/syscall.h +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef _INTERNAL_SYSCALL_H -#define _INTERNAL_SYSCALL_H - -//#include -#include "syscall_arch.h" - -#ifndef __scc -#define __scc(X) ((long) (X)) -typedef long syscall_arg_t; -#endif - -#if defined(__PIC__) && (100*__GNUC__+__GNUC_MINOR__ >= 303) -__attribute__((visibility("protected"))) -#endif -long __syscall_ret(unsigned long), __syscall(syscall_arg_t, ...), - __syscall_cp(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, - syscall_arg_t, syscall_arg_t, syscall_arg_t); - -#define __syscall1(n,a) __syscall1(n,__scc(a)) -#define __syscall2(n,a,b) __syscall2(n,__scc(a),__scc(b)) -#define __syscall3(n,a,b,c) __syscall3(n,__scc(a),__scc(b),__scc(c)) -#define __syscall4(n,a,b,c,d) __syscall4(n,__scc(a),__scc(b),__scc(c),__scc(d)) -#define __syscall5(n,a,b,c,d,e) __syscall5(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e)) -#define __syscall6(n,a,b,c,d,e,f) __syscall6(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) -#define __syscall7(n,a,b,c,d,e,f,g) (__syscall)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f),__scc(g)) - -#define __SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n -#define __SYSCALL_NARGS(...) __SYSCALL_NARGS_X(__VA_ARGS__,7,6,5,4,3,2,1,0,) -#define __SYSCALL_CONCAT_X(a,b) a##b -#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X(a,b) -#define __SYSCALL_DISP(b,...) __SYSCALL_CONCAT(b,__SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) - -#define __syscall(...) __SYSCALL_DISP(__syscall,__VA_ARGS__) -#define syscall(...) __syscall_ret(__syscall(__VA_ARGS__)) - -#define socketcall __socketcall -#define socketcall_cp __socketcall_cp - -#define __syscall_cp0(n) (__syscall_cp)(n,0,0,0,0,0,0) -#define __syscall_cp1(n,a) (__syscall_cp)(n,__scc(a),0,0,0,0,0) -#define __syscall_cp2(n,a,b) (__syscall_cp)(n,__scc(a),__scc(b),0,0,0,0) -#define __syscall_cp3(n,a,b,c) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),0,0,0) -#define __syscall_cp4(n,a,b,c,d) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),0,0) -#define __syscall_cp5(n,a,b,c,d,e) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),0) -#define __syscall_cp6(n,a,b,c,d,e,f) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) - -#define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__) -#define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__)) - -#ifdef SYS_socket -#define __socketcall(nm,a,b,c,d,e,f) syscall(SYS_##nm, a, b, c, d, e, f) -#define __socketcall_cp(nm,a,b,c,d,e,f) syscall_cp(SYS_##nm, a, b, c, d, e, f) -#else -#define __socketcall(nm,a,b,c,d,e,f) syscall(SYS_socketcall, __SC_##nm, \ - ((long [6]){ (long)a, (long)b, (long)c, (long)d, (long)e, (long)f })) -#define __socketcall_cp(nm,a,b,c,d,e,f) syscall_cp(SYS_socketcall, __SC_##nm, \ - ((long [6]){ (long)a, (long)b, (long)c, (long)d, (long)e, (long)f })) -#endif - -/* fixup legacy 16-bit junk */ - -#ifdef SYS_getuid32 -#undef SYS_lchown -#undef SYS_getuid -#undef SYS_getgid -#undef SYS_geteuid -#undef SYS_getegid -#undef SYS_setreuid -#undef SYS_setregid -#undef SYS_getgroups -#undef SYS_setgroups -#undef SYS_fchown -#undef SYS_setresuid -#undef SYS_getresuid -#undef SYS_setresgid -#undef SYS_getresgid -#undef SYS_chown -#undef SYS_setuid -#undef SYS_setgid -#undef SYS_setfsuid -#undef SYS_setfsgid -#define SYS_lchown SYS_lchown32 -#define SYS_getuid SYS_getuid32 -#define SYS_getgid SYS_getgid32 -#define SYS_geteuid SYS_geteuid32 -#define SYS_getegid SYS_getegid32 -#define SYS_setreuid SYS_setreuid32 -#define SYS_setregid SYS_setregid32 -#define SYS_getgroups SYS_getgroups32 -#define SYS_setgroups SYS_setgroups32 -#define SYS_fchown SYS_fchown32 -#define SYS_setresuid SYS_setresuid32 -#define SYS_getresuid SYS_getresuid32 -#define SYS_setresgid SYS_setresgid32 -#define SYS_getresgid SYS_getresgid32 -#define SYS_chown SYS_chown32 -#define SYS_setuid SYS_setuid32 -#define SYS_setgid SYS_setgid32 -#define SYS_setfsuid SYS_setfsuid32 -#define SYS_setfsgid SYS_setfsgid32 -#endif - - -/* fixup legacy 32-bit-vs-lfs64 junk */ - -#ifdef SYS_fcntl64 -#undef SYS_fcntl -#define SYS_fcntl SYS_fcntl64 -#endif - -#ifdef SYS_getdents64 -#undef SYS_getdents -#define SYS_getdents SYS_getdents64 -#endif - -#ifdef SYS_ftruncate64 -#undef SYS_ftruncate -#undef SYS_truncate -#define SYS_ftruncate SYS_ftruncate64 -#define SYS_truncate SYS_truncate64 -#endif - -#ifdef SYS_stat64 -#undef SYS_stat -#undef SYS_fstat -#undef SYS_lstat -#undef SYS_statfs -#undef SYS_fstatfs -#define SYS_stat SYS_stat64 -#define SYS_fstat SYS_fstat64 -#define SYS_lstat SYS_lstat64 -#define SYS_statfs SYS_statfs64 -#define SYS_fstatfs SYS_fstatfs64 -#endif - -#if defined(SYS_newfstatat) -#undef SYS_fstatat -#define SYS_fstatat SYS_newfstatat -#elif defined(SYS_fstatat64) -#undef SYS_fstatat -#define SYS_fstatat SYS_fstatat64 -#endif - -#ifdef SYS_ugetrlimit -#undef SYS_getrlimit -#define SYS_getrlimit SYS_ugetrlimit -#endif - -#ifdef SYS__newselect -#undef SYS_select -#define SYS_select SYS__newselect -#endif - -#ifdef SYS_pread64 -#undef SYS_pread -#undef SYS_pwrite -#define SYS_pread SYS_pread64 -#define SYS_pwrite SYS_pwrite64 -#endif - -#ifdef SYS_fadvise64_64 -#undef SYS_fadvise -#define SYS_fadvise SYS_fadvise64_64 -#endif - -#endif diff --git a/user/libc/internal/syscall.s b/user/libc/internal/syscall.s deleted file mode 100644 index c84e1540..00000000 --- a/user/libc/internal/syscall.s +++ /dev/null @@ -1,16 +0,0 @@ -.global __syscall -.type __syscall,%function -__syscall: - mov ip,sp - stmfd sp!,{r4,r5,r6,r7} - mov r7,r0 - mov r0,r1 - mov r1,r2 - mov r2,r3 - ldmfd ip,{r3,r4,r5,r6} - svc 0 - ldmfd sp!,{r4,r5,r6,r7} - tst lr,#1 - moveq pc,lr - bx lr - diff --git a/user/libc/internal/syscall_ret.c b/user/libc/internal/syscall_ret.c deleted file mode 100644 index d99f4a50..00000000 --- a/user/libc/internal/syscall_ret.c +++ /dev/null @@ -1,10 +0,0 @@ -#include - -long __syscall_ret(unsigned long r) -{ - if (r > -4096UL) { - errno = -r; - return -1; - } - return r; -} diff --git a/user/libc/malloc/malloc_syscalls.c b/user/libc/malloc/malloc_syscalls.c deleted file mode 100644 index 30f6d946..00000000 --- a/user/libc/malloc/malloc_syscalls.c +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include -#include "../arch/arm/syscall_arch.h" -#include "stdint.h" - -/** - * malloc does a system call to allocate memory on the user heap - * - * @param size of the block of memory allocated - * @param uint32_t size > 0 - * @return returns a pointer to the allocated block of memory - returns 0 if size is less than 1 - */ -void* malloc(uint32_t size) -{ - if (size <= 0) - { - return 0; - } - //size will be passed into R0 for the syscall. - long retval = __syscall1(SYSCALL_MALLOC,(long) size); - - //returns a pointer to begginning of allocated block(s) - return (void*)retval; -} - -/** - * aligned alloc does a system call to allocate memory on the user heap - * according to a specified alignemnt - * - * @param size of the block of memory allocated, and alignment desired - * @param uint32_t size >0, uint32_t alignment >0 - * @return returns a pointer to the allocated block of memory - * that is a multiple of the specified allignement - * returns 0 if size or alignment are less than 1 - */ -void* aligned_alloc(uint32_t size, uint32_t alignment) -{ - if (size <= 0 || alignment <= 0) - { - return 0; - } - //syscall with two arguments - //size passed into R0, alignment passed into R1 - long retval = __syscall2(SYSCALL_ALIGNED_ALLOC, (long) size, (long) alignment); - //returns a pointer to begginning of allocated block(s) - return (void*) retval; -} - -/** - * free does a system call to free an allocated block of memory on the heap - * - * @param pointer to a block of memeory on the heap, does nothing if pointer is null - * @param void* ptr - * @return nothing returned - */ -void free(void* ptr) -{ - //if null pointer, do nothing - if (ptr == 0) - { - return 0; - } - - //pointer of allocated block passed into R0 - long retval = __syscall1(SYSCALL_FREE,(long)ptr); - - //nothing returned -} - - \ No newline at end of file diff --git a/user/libc/math/frexp.c b/user/libc/math/frexp.c deleted file mode 100644 index 27b6266e..00000000 --- a/user/libc/math/frexp.c +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include - -double frexp(double x, int *e) -{ - union { double d; uint64_t i; } y = { x }; - int ee = y.i>>52 & 0x7ff; - - if (!ee) { - if (x) { - x = frexp(x*0x1p64, e); - *e -= 64; - } else *e = 0; - return x; - } else if (ee == 0x7ff) { - return x; - } - - *e = ee - 0x3fe; - y.i &= 0x800fffffffffffffull; - y.i |= 0x3fe0000000000000ull; - return y.d; -} diff --git a/user/libc/math/frexpl.c b/user/libc/math/frexpl.c deleted file mode 100644 index 3c1b5537..00000000 --- a/user/libc/math/frexpl.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "libm.h" - -#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 -long double frexpl(long double x, int *e) -{ - return frexp(x, e); -} -#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 -long double frexpl(long double x, int *e) -{ - union ldshape u = {x}; - int ee = u.i.se & 0x7fff; - - if (!ee) { - if (x) { - x = frexpl(x*0x1p120, e); - *e -= 120; - } else *e = 0; - return x; - } else if (ee == 0x7fff) { - return x; - } - - *e = ee - 0x3ffe; - u.i.se &= 0x8000; - u.i.se |= 0x3ffe; - return u.f; -} -#endif diff --git a/user/libc/multibyte/wcrtomb.c b/user/libc/multibyte/wcrtomb.c deleted file mode 100644 index 59f733db..00000000 --- a/user/libc/multibyte/wcrtomb.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This code was written by Rich Felker in 2010; no copyright is claimed. - * This code is in the public domain. Attribution is appreciated but - * unnecessary. - */ - -#include -#include - -size_t wcrtomb(char *restrict s, wchar_t wc, mbstate_t *restrict st) -{ - if (!s) return 1; - if ((unsigned)wc < 0x80) { - *s = wc; - return 1; - } else if ((unsigned)wc < 0x800) { - *s++ = 0xc0 | (wc>>6); - *s = 0x80 | (wc&0x3f); - return 2; - } else if ((unsigned)wc < 0xd800 || (unsigned)wc-0xe000 < 0x2000) { - *s++ = 0xe0 | (wc>>12); - *s++ = 0x80 | ((wc>>6)&0x3f); - *s = 0x80 | (wc&0x3f); - return 3; - } else if ((unsigned)wc-0x10000 < 0x100000) { - *s++ = 0xf0 | (wc>>18); - *s++ = 0x80 | ((wc>>12)&0x3f); - *s++ = 0x80 | ((wc>>6)&0x3f); - *s = 0x80 | (wc&0x3f); - return 4; - } - errno = EILSEQ; - return -1; -} diff --git a/user/libc/multibyte/wctob.c b/user/libc/multibyte/wctob.c deleted file mode 100644 index d6353ee1..00000000 --- a/user/libc/multibyte/wctob.c +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include - -int wctob(wint_t c) -{ - if (c < 128U) return c; - return EOF; -} diff --git a/user/libc/multibyte/wctomb.c b/user/libc/multibyte/wctomb.c deleted file mode 100644 index de7ed84d..00000000 --- a/user/libc/multibyte/wctomb.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * This code was written by Rich Felker in 2010; no copyright is claimed. - * This code is in the public domain. Attribution is appreciated but - * unnecessary. - */ - -#include -#include - -int wctomb(char *s, wchar_t wc) -{ - if (!s) return 0; - return wcrtomb(s, wc, 0); -} diff --git a/user/libc/stdio/__lockfile.c b/user/libc/stdio/__lockfile.c deleted file mode 100644 index f2f27db6..00000000 --- a/user/libc/stdio/__lockfile.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "stdio_impl.h" -//#include "pthread_impl.h" - -int __lockfile(FILE *f) -{ -#if 0 - int owner, tid = __pthread_self()->tid; - if (f->lock == tid) - return 0; - while ((owner = a_cas(&f->lock, 0, tid))) - __wait(&f->lock, &f->waiters, owner, 1); - return 1; -#endif -} - -void __unlockfile(FILE *f) -{ -#if 0 - a_store(&f->lock, 0); - - /* The following read is technically invalid under situations - * of self-synchronized destruction. Another thread may have - * called fclose as soon as the above store has completed. - * Nonetheless, since FILE objects always live in memory - * obtained by malloc from the heap, it's safe to assume - * the dereferences below will not fault. In the worst case, - * a spurious syscall will be made. If the implementation of - * malloc changes, this assumption needs revisiting. */ - - if (f->waiters) __wake(&f->lock, 1, 1); -#endif -} diff --git a/user/libc/stdio/__stdio_close.c b/user/libc/stdio/__stdio_close.c deleted file mode 100644 index 838da30b..00000000 --- a/user/libc/stdio/__stdio_close.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "stdio_impl.h" - -int __stdio_close(FILE *f) -{ - //return syscall(SYS_close, f->fd); -} diff --git a/user/libc/stdio/__stdio_exit.c b/user/libc/stdio/__stdio_exit.c deleted file mode 100644 index 0fb33234..00000000 --- a/user/libc/stdio/__stdio_exit.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "stdio_impl.h" - -static FILE *const dummy_file = 0; -weak_alias(dummy_file, __stdin_used); -weak_alias(dummy_file, __stdout_used); -weak_alias(dummy_file, __stderr_used); - -static void close_file(FILE *f) -{ - if (!f) return; - FFINALLOCK(f); - if (f->wpos > f->wbase) f->write(f, 0, 0); - if (f->rpos < f->rend) f->seek(f, f->rpos-f->rend, SEEK_CUR); -} - -void __stdio_exit(void) -{ - FILE *f; - OFLLOCK(); - for (f=libc.ofl_head; f; f=f->next) close_file(f); - close_file(__stdin_used); - close_file(__stdout_used); -} diff --git a/user/libc/stdio/__stdio_seek.c b/user/libc/stdio/__stdio_seek.c deleted file mode 100644 index cda21202..00000000 --- a/user/libc/stdio/__stdio_seek.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "stdio_impl.h" - -#define SYS_lseek 102 - -off_t __stdio_seek(FILE *f, off_t off, int whence) -{ - off_t ret; -#ifdef SYS__llseek - if (syscall(SYS__llseek, f->fd, off>>32, off, &ret, whence)<0) - ret = -1; -#else - ret = syscall(SYS_lseek, f->fd, off, whence); -#endif - return ret; -} diff --git a/user/libc/stdio/__stdio_write.c b/user/libc/stdio/__stdio_write.c deleted file mode 100644 index 3812c655..00000000 --- a/user/libc/stdio/__stdio_write.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "stdio_impl.h" -#include -// #include - -#define SYS_writev 101 - -static void cleanup(void *p) -{ - FILE *f = p; - if (!f->lockcount) __unlockfile(f); -} - -size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len) -{ - struct iovec iovs[2] = { - { .iov_base = f->wbase, .iov_len = f->wpos-f->wbase }, - { .iov_base = (void *)buf, .iov_len = len } - }; - struct iovec *iov = iovs; - size_t rem = iov[0].iov_len + iov[1].iov_len; - int iovcnt = 2; - ssize_t cnt; - for (;;) { -#if 0 - if (libc.main_thread) { - pthread_cleanup_push(cleanup, f); - cnt = syscall_cp(SYS_writev, f->fd, iov, iovcnt); - pthread_cleanup_pop(0); - } else { -#endif - cnt = syscall(SYS_writev, f->fd, iov, iovcnt); -#if 0 - } -#endif - if (cnt == rem) { - f->wend = f->buf + f->buf_size; - f->wpos = f->wbase = f->buf; - return len; - } - if (cnt < 0) { - f->wpos = f->wbase = f->wend = 0; - f->flags |= F_ERR; - return iovcnt == 2 ? 0 : len-iov[0].iov_len; - } - rem -= cnt; - if (cnt > iov[0].iov_len) { - f->wpos = f->wbase = f->buf; - cnt -= iov[0].iov_len; - iov++; iovcnt--; - } else if (iovcnt == 2) { - f->wbase += cnt; - } - iov[0].iov_base = (char *)iov[0].iov_base + cnt; - iov[0].iov_len -= cnt; - } -} diff --git a/user/libc/stdio/__stdout_write.c b/user/libc/stdio/__stdout_write.c deleted file mode 100644 index e8119da3..00000000 --- a/user/libc/stdio/__stdout_write.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "stdio_impl.h" -#include -#include - -size_t __stdout_write(FILE *f, const unsigned char *buf, size_t len) -{ - struct termios tio; - f->write = __stdio_write; - //if (!(f->flags & F_SVB) && __syscall(SYS_ioctl, f->fd, TCGETS, &tio)) - // f->lbf = -1; - return __stdio_write(f, buf, len); -} diff --git a/user/libc/stdio/__towrite.c b/user/libc/stdio/__towrite.c deleted file mode 100644 index 23658e4c..00000000 --- a/user/libc/stdio/__towrite.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "stdio_impl.h" - -int __towrite(FILE *f) -{ - f->mode |= f->mode-1; - if (f->flags & (F_NOWR)) { - f->flags |= F_ERR; - return EOF; - } - /* Clear read buffer (easier than summoning nasal demons) */ - f->rpos = f->rend = 0; - /* Activate write through the buffer. */ - f->wpos = f->wbase = f->buf; - f->wend = f->buf + f->buf_size; - - return 0; -} - -const int __towrite_used = 1; - -void __stdio_exit(void); - -void __flush_on_exit() -{ - __stdio_exit(); -} diff --git a/user/libc/stdio/fwrite.c b/user/libc/stdio/fwrite.c deleted file mode 100644 index 1956af2e..00000000 --- a/user/libc/stdio/fwrite.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "stdio_impl.h" -#include - -size_t __fwritex(const unsigned char *restrict s, size_t l, FILE *restrict f) -{ - size_t i=0; - if (!f->wend && __towrite(f)) return 0; - if (l > f->wend - f->wpos) return f->write(f, s, l); - - if (f->lbf >= 0) { - /* Match /^(.*\n|)/ */ - for (i=l; i && s[i-1] != '\n'; i--); - if (i) { - if (f->write(f, s, i) < i) - return i; - s += i; - l -= i; - } - } - - memcpy(f->wpos, s, l); - f->wpos += l; - return l+i; -} - -size_t fwrite(const void *restrict src, size_t size, size_t nmemb, FILE *restrict f) -{ - size_t k, l = size*nmemb; - if (!l) return l; - FLOCK(f); - k = __fwritex(src, l, f); - FUNLOCK(f); - return k==l ? nmemb : k/size; -} - -weak_alias(fwrite, fwrite_unlocked); diff --git a/user/libc/stdio/printf.c b/user/libc/stdio/printf.c deleted file mode 100644 index 55bf6c65..00000000 --- a/user/libc/stdio/printf.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include "../arch/arm/syscall_arch.h" - -int printf(const char *restrict fmt, ...) -{ - //int ret; - //va_list ap; - //va_start(ap, fmt); - //ret = vfprintf(stdout, fmt, ap); - //va_end(ap); - //return ret; - long error = __syscall1(SYSCALL_PRINTF, (long)fmt); - return error; -} diff --git a/user/libc/stdio/stdout.c b/user/libc/stdio/stdout.c deleted file mode 100644 index 3855dd0b..00000000 --- a/user/libc/stdio/stdout.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "stdio_impl.h" - -static unsigned char buf[BUFSIZ+UNGET]; -static FILE f = { - .buf = buf+UNGET, - .buf_size = sizeof buf-UNGET, - .fd = 1, - .flags = F_PERM | F_NORD, - .lbf = '\n', - .write = __stdout_write, - .seek = __stdio_seek, - .close = __stdio_close, - .lock = -1, -}; -FILE *const stdout = &f; -FILE *const __stdout_used = &f; diff --git a/user/libc/stdio/vfprintf.c b/user/libc/stdio/vfprintf.c deleted file mode 100644 index ce0bf7b3..00000000 --- a/user/libc/stdio/vfprintf.c +++ /dev/null @@ -1,689 +0,0 @@ -#include "stdio_impl.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Some useful macros */ - -#define MAX(a,b) ((a)>(b) ? (a) : (b)) -#define MIN(a,b) ((a)<(b) ? (a) : (b)) -#define CONCAT2(x,y) x ## y -#define CONCAT(x,y) CONCAT2(x,y) - -/* Convenient bit representation for modifier flags, which all fall - * within 31 codepoints of the space character. */ - -#define ALT_FORM (1U<<'#'-' ') -#define ZERO_PAD (1U<<'0'-' ') -#define LEFT_ADJ (1U<<'-'-' ') -#define PAD_POS (1U<<' '-' ') -#define MARK_POS (1U<<'+'-' ') -#define GROUPED (1U<<'\''-' ') - -#define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS|GROUPED) - -#if UINT_MAX == ULONG_MAX -#define LONG_IS_INT -#endif - -#if SIZE_MAX != ULONG_MAX || UINTMAX_MAX != ULLONG_MAX -#define ODD_TYPES -#endif - -/* State machine to accept length modifiers + conversion specifiers. - * Result is 0 on failure, or an argument type to pop on success. */ - -enum { - BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE, - ZTPRE, JPRE, - STOP, - PTR, INT, UINT, ULLONG, -#ifndef LONG_IS_INT - LONG, ULONG, -#else -#define LONG INT -#define ULONG UINT -#endif - SHORT, USHORT, CHAR, UCHAR, -#ifdef ODD_TYPES - LLONG, SIZET, IMAX, UMAX, PDIFF, UIPTR, -#else -#define LLONG ULLONG -#define SIZET ULONG -#define IMAX LLONG -#define UMAX ULLONG -#define PDIFF LONG -#define UIPTR ULONG -#endif - DBL, LDBL, - NOARG, - MAXSTATE -}; - -#define S(x) [(x)-'A'] - -static const unsigned char states[]['z'-'A'+1] = { - { /* 0: bare types */ - S('d') = INT, S('i') = INT, - S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT, - S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL, - S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL, - S('c') = CHAR, S('C') = INT, - S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR, - S('m') = NOARG, - S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE, - S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE, - }, { /* 1: l-prefixed */ - S('d') = LONG, S('i') = LONG, - S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG, - S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL, - S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL, - S('c') = INT, S('s') = PTR, S('n') = PTR, - S('l') = LLPRE, - }, { /* 2: ll-prefixed */ - S('d') = LLONG, S('i') = LLONG, - S('o') = ULLONG, S('u') = ULLONG, - S('x') = ULLONG, S('X') = ULLONG, - S('n') = PTR, - }, { /* 3: h-prefixed */ - S('d') = SHORT, S('i') = SHORT, - S('o') = USHORT, S('u') = USHORT, - S('x') = USHORT, S('X') = USHORT, - S('n') = PTR, - S('h') = HHPRE, - }, { /* 4: hh-prefixed */ - S('d') = CHAR, S('i') = CHAR, - S('o') = UCHAR, S('u') = UCHAR, - S('x') = UCHAR, S('X') = UCHAR, - S('n') = PTR, - }, { /* 5: L-prefixed */ - S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL, - S('E') = LDBL, S('F') = LDBL, S('G') = LDBL, S('A') = LDBL, - S('n') = PTR, - }, { /* 6: z- or t-prefixed (assumed to be same size) */ - S('d') = PDIFF, S('i') = PDIFF, - S('o') = SIZET, S('u') = SIZET, - S('x') = SIZET, S('X') = SIZET, - S('n') = PTR, - }, { /* 7: j-prefixed */ - S('d') = IMAX, S('i') = IMAX, - S('o') = UMAX, S('u') = UMAX, - S('x') = UMAX, S('X') = UMAX, - S('n') = PTR, - } -}; - -#define OOB(x) ((unsigned)(x)-'A' > 'z'-'A') - -union arg -{ - uintmax_t i; - long double f; - void *p; -}; - -static void pop_arg(union arg *arg, int type, va_list *ap) -{ - /* Give the compiler a hint for optimizing the switch. */ - if ((unsigned)type > MAXSTATE) return; - switch (type) { - case PTR: arg->p = va_arg(*ap, void *); - break; case INT: arg->i = va_arg(*ap, int); - break; case UINT: arg->i = va_arg(*ap, unsigned int); -#ifndef LONG_IS_INT - break; case LONG: arg->i = va_arg(*ap, long); - break; case ULONG: arg->i = va_arg(*ap, unsigned long); -#endif - break; case ULLONG: arg->i = va_arg(*ap, unsigned long long); - break; case SHORT: arg->i = (short)va_arg(*ap, int); - break; case USHORT: arg->i = (unsigned short)va_arg(*ap, int); - break; case CHAR: arg->i = (signed char)va_arg(*ap, int); - break; case UCHAR: arg->i = (unsigned char)va_arg(*ap, int); -#ifdef ODD_TYPES - break; case LLONG: arg->i = va_arg(*ap, long long); - break; case SIZET: arg->i = va_arg(*ap, size_t); - break; case IMAX: arg->i = va_arg(*ap, intmax_t); - break; case UMAX: arg->i = va_arg(*ap, uintmax_t); - break; case PDIFF: arg->i = va_arg(*ap, ptrdiff_t); - break; case UIPTR: arg->i = (uintptr_t)va_arg(*ap, void *); -#endif - break; case DBL: arg->f = va_arg(*ap, double); - break; case LDBL: arg->f = va_arg(*ap, long double); - } -} - -static void out(FILE *f, const char *s, size_t l) -{ - while(1); - __fwritex((void *)s, l, f); -} - -static void pad(FILE *f, char c, int w, int l, int fl) -{ - char pad[256]; - if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return; - l = w - l; - memset(pad, c, l>sizeof pad ? sizeof pad : l); - for (; l >= sizeof pad; l -= sizeof pad) - out(f, pad, sizeof pad); - out(f, pad, l); -} - -static const char xdigits[16] = { - "0123456789ABCDEF" -}; - -static char *fmt_x(uintmax_t x, char *s, int lower) -{ - for (; x; x>>=4) *--s = xdigits[(x&15)]|lower; - return s; -} - -static char *fmt_o(uintmax_t x, char *s) -{ - for (; x; x>>=3) *--s = '0' + (x&7); - return s; -} - -static char *fmt_u(uintmax_t x, char *s) -{ - unsigned long y; - for ( ; x>ULONG_MAX; x/=10) *--s = '0' + x%10; - for (y=x; y; y/=10) *--s = '0' + y%10; - return s; -} - -/* Do not override this check. The floating point printing code below - * depends on the float.h constants being right. If they are wrong, it - * may overflow the stack. */ -#if LDBL_MANT_DIG == 53 -typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)]; -#endif - -static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) -{ - uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion - + (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion - uint32_t *a, *d, *r, *z; - int e2=0, e, i, j, l; - char buf[9+LDBL_MANT_DIG/4], *s; - const char *prefix="-0X+0X 0X-0x+0x 0x"; - int pl; - char ebuf0[3*sizeof(int)], *ebuf=&ebuf0[3*sizeof(int)], *estr; - - pl=1; - if (signbit(y)) { - y=-y; - } else if (fl & MARK_POS) { - prefix+=3; - } else if (fl & PAD_POS) { - prefix+=6; - } else prefix++, pl=0; - - if (!isfinite(y)) { - char *s = (t&32)?"inf":"INF"; - if (y!=y) s=(t&32)?"nan":"NAN", pl=0; - pad(f, ' ', w, 3+pl, fl&~ZERO_PAD); - out(f, prefix, pl); - out(f, s, 3); - pad(f, ' ', w, 3+pl, fl^LEFT_ADJ); - return MAX(w, 3+pl); - } - - y = frexpl(y, &e2) * 2; - if (y) e2--; - - if ((t|32)=='a') { - long double round = 8.0; - int re; - - if (t&32) prefix += 9; - pl += 2; - - if (p<0 || p>=LDBL_MANT_DIG/4-1) re=0; - else re=LDBL_MANT_DIG/4-1-p; - - if (re) { - while (re--) round*=16; - if (*prefix=='-') { - y=-y; - y-=round; - y+=round; - y=-y; - } else { - y+=round; - y-=round; - } - } - - estr=fmt_u(e2<0 ? -e2 : e2, ebuf); - if (estr==ebuf) *--estr='0'; - *--estr = (e2<0 ? '-' : '+'); - *--estr = t+('p'-'a'); - - s=buf; - do { - int x=y; - *s++=xdigits[x]|(t&32); - y=16*(y-x); - if (s-buf==1 && (y||p>0||(fl&ALT_FORM))) *s++='.'; - } while (y); - - if (p && s-buf-2 < p) - l = (p+2) + (ebuf-estr); - else - l = (s-buf) + (ebuf-estr); - - pad(f, ' ', w, pl+l, fl); - out(f, prefix, pl); - pad(f, '0', w, pl+l, fl^ZERO_PAD); - out(f, buf, s-buf); - pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0); - out(f, estr, ebuf-estr); - pad(f, ' ', w, pl+l, fl^LEFT_ADJ); - return MAX(w, pl+l); - } - if (p<0) p=6; - - if (y) y *= 0x1p28, e2-=28; - - if (e2<0) a=r=z=big; - else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1; - - do { - *z = y; - y = 1000000000*(y-*z++); - } while (y); - - while (e2>0) { - uint32_t carry=0; - int sh=MIN(29,e2); - for (d=z-1; d>=a; d--) { - uint64_t x = ((uint64_t)*d<a) z--; - if (carry) *--a = carry; - e2-=sh; - } - while (e2<0) { - uint32_t carry=0, *b; - int sh=MIN(9,-e2), need=1+(p+LDBL_MANT_DIG/3+8)/9; - for (d=a; d>sh) + carry; - carry = (1000000000>>sh) * rm; - } - if (!*a) a++; - if (carry) *z++ = carry; - /* Avoid (slow!) computation past requested precision */ - b = (t|32)=='f' ? r : a; - if (z-b > need) z = b+need; - e2+=sh; - } - - if (a=i; i*=10, e++); - else e=0; - - /* Perform rounding: j is precision after the radix (possibly neg) */ - j = p - ((t|32)!='f')*e - ((t|32)=='g' && p); - if (j < 9*(z-r-1)) { - uint32_t x; - /* We avoid C's broken division of negative numbers */ - d = r + 1 + ((j+9*LDBL_MAX_EXP)/9 - LDBL_MAX_EXP); - j += 9*LDBL_MAX_EXP; - j %= 9; - for (i=10, j++; j<9; i*=10, j++); - x = *d % i; - /* Are there any significant digits past j? */ - if (x || d+1!=z) { - long double round = CONCAT(0x1p,LDBL_MANT_DIG); - long double small; - if (*d/i & 1) round += 2; - if (x 999999999) { - *d--=0; - (*d)++; - } - if (d=i; i*=10, e++); - } - } - if (z>d+1) z=d+1; - for (; !z[-1] && z>a; z--); - } - - if ((t|32)=='g') { - if (!p) p++; - if (p>e && e>=-4) { - t--; - p-=e+1; - } else { - t-=2; - p--; - } - if (!(fl&ALT_FORM)) { - /* Count trailing zeros in last place */ - if (z>a && z[-1]) for (i=10, j=0; z[-1]%i==0; i*=10, j++); - else j=9; - if ((t|32)=='f') - p = MIN(p,MAX(0,9*(z-r-1)-j)); - else - p = MIN(p,MAX(0,9*(z-r-1)+e-j)); - } - } - l = 1 + p + (p || (fl&ALT_FORM)); - if ((t|32)=='f') { - if (e>0) l+=e; - } else { - estr=fmt_u(e<0 ? -e : e, ebuf); - while(ebuf-estr<2) *--estr='0'; - *--estr = (e<0 ? '-' : '+'); - *--estr = t; - l += ebuf-estr; - } - - pad(f, ' ', w, pl+l, fl); - out(f, prefix, pl); - pad(f, '0', w, pl+l, fl^ZERO_PAD); - - if ((t|32)=='f') { - if (a>r) a=r; - for (d=a; d<=r; d++) { - char *s = fmt_u(*d, buf+9); - if (d!=a) while (s>buf) *--s='0'; - else if (s==buf+9) *--s='0'; - out(f, s, buf+9-s); - } - if (p || (fl&ALT_FORM)) out(f, ".", 1); - for (; d0; d++, p-=9) { - char *s = fmt_u(*d, buf+9); - while (s>buf) *--s='0'; - out(f, s, MIN(9,p)); - } - pad(f, '0', p+9, 9, 0); - } else { - if (z<=a) z=a+1; - for (d=a; d=0; d++) { - char *s = fmt_u(*d, buf+9); - if (s==buf+9) *--s='0'; - if (d!=a) while (s>buf) *--s='0'; - else { - out(f, s++, 1); - if (p>0||(fl&ALT_FORM)) out(f, ".", 1); - } - out(f, s, MIN(buf+9-s, p)); - p -= buf+9-s; - } - pad(f, '0', p+18, 18, 0); - out(f, estr, ebuf-estr); - } - - pad(f, ' ', w, pl+l, fl^LEFT_ADJ); - - return MAX(w, pl+l); -} - -static int getint(char **s) { - int i; - for (i=0; isdigit(**s); (*s)++) - i = 10*i + (**s-'0'); - return i; -} - -static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, int *nl_type) -{ - char *a, *z, *s=(char *)fmt; - unsigned l10n=0, fl; - int w, p; - union arg arg; - int argpos; - unsigned st, ps; - int cnt=0, l=0; - int i; - char buf[sizeof(uintmax_t)*3+3+LDBL_MANT_DIG/4]; - const char *prefix; - int t, pl; - wchar_t wc[2], *ws; - char mb[4]; - - for (;;) { - /* Update output count, end loop when fmt is exhausted */ - if (cnt >= 0) { - if (l > INT_MAX - cnt) { - errno = EOVERFLOW; - cnt = -1; - } else cnt += l; - } - if (!*s) break; - - /* Handle literal text and %% format specifiers */ - for (a=s; *s && *s!='%'; s++); - for (z=s; s[0]=='%' && s[1]=='%'; z++, s+=2); - l = z-a; - if (f) out(f, a, l); - if (l) continue; - - if (isdigit(s[1]) && s[2]=='$') { - l10n=1; - argpos = s[1]-'0'; - s+=3; - } else { - argpos = -1; - s++; - } - - /* Read modifier flags */ - for (fl=0; (unsigned)*s-' '<32 && (FLAGMASK&(1U<<*s-' ')); s++) - fl |= 1U<<*s-' '; - - /* Read field width */ - if (*s=='*') { - if (isdigit(s[1]) && s[2]=='$') { - l10n=1; - nl_type[s[1]-'0'] = INT; - w = nl_arg[s[1]-'0'].i; - s+=3; - } else if (!l10n) { - w = f ? va_arg(*ap, int) : 0; - s++; - } else return -1; - if (w<0) fl|=LEFT_ADJ, w=-w; - } else if ((w=getint(&s))<0) return -1; - - /* Read precision */ - if (*s=='.' && s[1]=='*') { - if (isdigit(s[2]) && s[3]=='$') { - nl_type[s[2]-'0'] = INT; - p = nl_arg[s[2]-'0'].i; - s+=4; - } else if (!l10n) { - p = f ? va_arg(*ap, int) : 0; - s+=2; - } else return -1; - } else if (*s=='.') { - s++; - p = getint(&s); - } else p = -1; - - /* Format specifier state machine */ - st=0; - do { - if (OOB(*s)) return -1; - ps=st; - st=states[st]S(*s++); - } while (st-1=0) return -1; - } else { - if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos]; - else if (f) pop_arg(&arg, st, ap); - else return 0; - } - - if (!f) continue; - - z = buf + sizeof(buf); - prefix = "-+ 0X0x"; - pl = 0; - t = s[-1]; - - /* Transform ls,lc -> S,C */ - if (ps && (t&15)==3) t&=~32; - - /* - and 0 flags are mutually exclusive */ - if (fl & LEFT_ADJ) fl &= ~ZERO_PAD; - - switch(t) { - case 'n': - switch(ps) { - case BARE: *(int *)arg.p = cnt; break; - case LPRE: *(long *)arg.p = cnt; break; - case LLPRE: *(long long *)arg.p = cnt; break; - case HPRE: *(unsigned short *)arg.p = cnt; break; - case HHPRE: *(unsigned char *)arg.p = cnt; break; - case ZTPRE: *(size_t *)arg.p = cnt; break; - case JPRE: *(uintmax_t *)arg.p = cnt; break; - } - continue; - case 'p': - p = MAX(p, 2*sizeof(void*)); - t = 'x'; - fl |= ALT_FORM; - case 'x': case 'X': - a = fmt_x(arg.i, z, t&32); - if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2; - if (0) { - case 'o': - a = fmt_o(arg.i, z); - if ((fl&ALT_FORM) && arg.i) prefix+=5, pl=1; - } if (0) { - case 'd': case 'i': - pl=1; - if (arg.i>INTMAX_MAX) { - arg.i=-arg.i; - } else if (fl & MARK_POS) { - prefix++; - } else if (fl & PAD_POS) { - prefix+=2; - } else pl=0; - case 'u': - a = fmt_u(arg.i, z); - } - if (p>=0) fl &= ~ZERO_PAD; - if (!arg.i && !p) { - a=z; - break; - } - p = MAX(p, z-a + !arg.i); - break; - case 'c': - *(a=z-(p=1))=arg.i; - fl &= ~ZERO_PAD; - break; - case 'm': - if (1) a = strerror(errno); else - case 's': - a = arg.p ? arg.p : "(null)"; - z = memchr(a, 0, p); - if (!z) z=a+p; - else p=z-a; - fl &= ~ZERO_PAD; - break; - case 'C': - wc[0] = arg.i; - wc[1] = 0; - arg.p = wc; - p = -1; - case 'S': - ws = arg.p; - for (i=l=0; i<0U+p && *ws && (l=wctomb(mb, *ws++))>=0 && l<=0U+p-i; i+=l); - if (l<0) return -1; - p = i; - pad(f, ' ', w, p, fl); - ws = arg.p; - for (i=0; i<0U+p && *ws && i+(l=wctomb(mb, *ws++))<=p; i+=l) - out(f, mb, l); - pad(f, ' ', w, p, fl^LEFT_ADJ); - l = w>p ? w : p; - continue; - case 'e': case 'f': case 'g': case 'a': - case 'E': case 'F': case 'G': case 'A': - l = fmt_fp(f, arg.f, w, p, fl, t); - continue; - } - - if (p < z-a) p = z-a; - if (w < pl+p) w = pl+p; - - pad(f, ' ', w, pl+p, fl); - out(f, prefix, pl); - pad(f, '0', w, pl+p, fl^ZERO_PAD); - pad(f, '0', p, z-a, 0); - out(f, a, z-a); - pad(f, ' ', w, pl+p, fl^LEFT_ADJ); - - l = w; - } - - if (f) return cnt; - if (!l10n) return 0; - - for (i=1; i<=NL_ARGMAX && nl_type[i]; i++) - pop_arg(nl_arg+i, nl_type[i], ap); - for (; i<=NL_ARGMAX && !nl_type[i]; i++); - if (i<=NL_ARGMAX) return -1; - return 1; -} - -int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) -{ - va_list ap2; - int nl_type[NL_ARGMAX+1] = {0}; - union arg nl_arg[NL_ARGMAX+1]; - unsigned char internal_buf[80], *saved_buf = 0; - int ret; - - /* the copy allows passing va_list* even if va_list is an array */ - va_copy(ap2, ap); - if (printf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) { - va_end(ap2); - return -1; - } - - FLOCK(f); - if (!f->buf_size) { - saved_buf = f->buf; - f->wpos = f->wbase = f->buf = internal_buf; - f->buf_size = sizeof internal_buf; - f->wend = internal_buf + sizeof internal_buf; - } - ret = printf_core(f, fmt, &ap2, nl_arg, nl_type); - if (saved_buf) { - f->write(f, 0, 0); - if (!f->wpos) ret = -1; - f->buf = saved_buf; - f->buf_size = 0; - f->wpos = f->wbase = f->wend = 0; - } - FUNLOCK(f); - va_end(ap2); - return ret; -} diff --git a/user/libc/string/memchr.c b/user/libc/string/memchr.c deleted file mode 100644 index 4daff7bb..00000000 --- a/user/libc/string/memchr.c +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include - -#define SS (sizeof(size_t)) -#define ALIGN (sizeof(size_t)-1) -#define ONES ((size_t)-1/UCHAR_MAX) -#define HIGHS (ONES * (UCHAR_MAX/2+1)) -#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS) - -void *memchr(const void *src, int c, size_t n) -{ - const unsigned char *s = src; - c = (unsigned char)c; - for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--); - if (n && *s != c) { - const size_t *w; - size_t k = ONES * c; - for (w = (const void *)s; n>=SS && !HASZERO(*w^k); w++, n-=SS); - for (s = (const void *)w; n && *s != c; s++, n--); - } - return n ? (void *)s : 0; -} diff --git a/user/libc/string/memcpy.c b/user/libc/string/memcpy.c deleted file mode 100644 index 06e88742..00000000 --- a/user/libc/string/memcpy.c +++ /dev/null @@ -1,124 +0,0 @@ -#include -#include -#include - -void *memcpy(void *restrict dest, const void *restrict src, size_t n) -{ - unsigned char *d = dest; - const unsigned char *s = src; - -#ifdef __GNUC__ - -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define LS >> -#define RS << -#else -#define LS << -#define RS >> -#endif - - typedef uint32_t __attribute__((__may_alias__)) u32; - uint32_t w, x; - - for (; (uintptr_t)s % 4 && n; n--) *d++ = *s++; - - if ((uintptr_t)d % 4 == 0) { - for (; n>=16; s+=16, d+=16, n-=16) { - *(u32 *)(d+0) = *(u32 *)(s+0); - *(u32 *)(d+4) = *(u32 *)(s+4); - *(u32 *)(d+8) = *(u32 *)(s+8); - *(u32 *)(d+12) = *(u32 *)(s+12); - } - if (n&8) { - *(u32 *)(d+0) = *(u32 *)(s+0); - *(u32 *)(d+4) = *(u32 *)(s+4); - d += 8; s += 8; - } - if (n&4) { - *(u32 *)(d+0) = *(u32 *)(s+0); - d += 4; s += 4; - } - if (n&2) { - *d++ = *s++; *d++ = *s++; - } - if (n&1) { - *d = *s; - } - return dest; - } - - if (n >= 32) switch ((uintptr_t)d % 4) { - case 1: - w = *(u32 *)s; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - n -= 3; - for (; n>=17; s+=16, d+=16, n-=16) { - x = *(u32 *)(s+1); - *(u32 *)(d+0) = (w LS 24) | (x RS 8); - w = *(u32 *)(s+5); - *(u32 *)(d+4) = (x LS 24) | (w RS 8); - x = *(u32 *)(s+9); - *(u32 *)(d+8) = (w LS 24) | (x RS 8); - w = *(u32 *)(s+13); - *(u32 *)(d+12) = (x LS 24) | (w RS 8); - } - break; - case 2: - w = *(u32 *)s; - *d++ = *s++; - *d++ = *s++; - n -= 2; - for (; n>=18; s+=16, d+=16, n-=16) { - x = *(u32 *)(s+2); - *(u32 *)(d+0) = (w LS 16) | (x RS 16); - w = *(u32 *)(s+6); - *(u32 *)(d+4) = (x LS 16) | (w RS 16); - x = *(u32 *)(s+10); - *(u32 *)(d+8) = (w LS 16) | (x RS 16); - w = *(u32 *)(s+14); - *(u32 *)(d+12) = (x LS 16) | (w RS 16); - } - break; - case 3: - w = *(u32 *)s; - *d++ = *s++; - n -= 1; - for (; n>=19; s+=16, d+=16, n-=16) { - x = *(u32 *)(s+3); - *(u32 *)(d+0) = (w LS 8) | (x RS 24); - w = *(u32 *)(s+7); - *(u32 *)(d+4) = (x LS 8) | (w RS 24); - x = *(u32 *)(s+11); - *(u32 *)(d+8) = (w LS 8) | (x RS 24); - w = *(u32 *)(s+15); - *(u32 *)(d+12) = (x LS 8) | (w RS 24); - } - break; - } - if (n&16) { - *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; - *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; - *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; - *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; - } - if (n&8) { - *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; - *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; - } - if (n&4) { - *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; - } - if (n&2) { - *d++ = *s++; *d++ = *s++; - } - if (n&1) { - *d = *s; - } - return dest; -#endif - - for (; n; n--) *d++ = *s++; - return dest; -} diff --git a/user/libc/string/memset.c b/user/libc/string/memset.c deleted file mode 100644 index f438b073..00000000 --- a/user/libc/string/memset.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include - -void *memset(void *dest, int c, size_t n) -{ - unsigned char *s = dest; - size_t k; - - /* Fill head and tail with minimal branching. Each - * conditional ensures that all the subsequently used - * offsets are well-defined and in the dest region. */ - - if (!n) return dest; - s[0] = s[n-1] = c; - if (n <= 2) return dest; - s[1] = s[n-2] = c; - s[2] = s[n-3] = c; - if (n <= 6) return dest; - s[3] = s[n-4] = c; - if (n <= 8) return dest; - - /* Advance pointer to align it at a 4-byte boundary, - * and truncate n to a multiple of 4. The previous code - * already took care of any head/tail that get cut off - * by the alignment. */ - - k = -(uintptr_t)s & 3; - s += k; - n -= k; - n &= -4; - -#ifdef __GNUC__ - typedef uint32_t __attribute__((__may_alias__)) u32; - typedef uint64_t __attribute__((__may_alias__)) u64; - - u32 c32 = ((u32)-1)/255 * (unsigned char)c; - - /* In preparation to copy 32 bytes at a time, aligned on - * an 8-byte bounary, fill head/tail up to 28 bytes each. - * As in the initial byte-based head/tail fill, each - * conditional below ensures that the subsequent offsets - * are valid (e.g. !(n<=24) implies n>=28). */ - - *(u32 *)(s+0) = c32; - *(u32 *)(s+n-4) = c32; - if (n <= 8) return dest; - *(u32 *)(s+4) = c32; - *(u32 *)(s+8) = c32; - *(u32 *)(s+n-12) = c32; - *(u32 *)(s+n-8) = c32; - if (n <= 24) return dest; - *(u32 *)(s+12) = c32; - *(u32 *)(s+16) = c32; - *(u32 *)(s+20) = c32; - *(u32 *)(s+24) = c32; - *(u32 *)(s+n-28) = c32; - *(u32 *)(s+n-24) = c32; - *(u32 *)(s+n-20) = c32; - *(u32 *)(s+n-16) = c32; - - /* Align to a multiple of 8 so we can fill 64 bits at a time, - * and avoid writing the same bytes twice as much as is - * practical without introducing additional branching. */ - - k = 24 + ((uintptr_t)s & 4); - s += k; - n -= k; - - /* If this loop is reached, 28 tail bytes have already been - * filled, so any remainder when n drops below 32 can be - * safely ignored. */ - - u64 c64 = c32 | ((u64)c32 << 32); - for (; n >= 32; n-=32, s+=32) { - *(u64 *)(s+0) = c64; - *(u64 *)(s+8) = c64; - *(u64 *)(s+16) = c64; - *(u64 *)(s+24) = c64; - } -#else - /* Pure C fallback with no aliasing violations. */ - for (; n; n--, s++) *s = c; -#endif - - return dest; -} diff --git a/user/libc/ulib/ulib.c b/user/libc/ulib/ulib.c deleted file mode 100644 index e69de29b..00000000 diff --git a/user/swi/swi.c b/user/swi/swi.c new file mode 100644 index 00000000..7688e2a6 --- /dev/null +++ b/user/swi/swi.c @@ -0,0 +1,10 @@ +int main() { + for (;;) { + asm volatile("ldr r1, =0x80008000 \n" + "mov r2, #42 \n" + "ldr r2, [r1] \n" + "mov r7, #4 \n" + "swi $0 \n"); + } + return 0; +} diff --git a/user/ulibc.h b/user/ulibc.h deleted file mode 100644 index e7ff4d23..00000000 --- a/user/ulibc.h +++ /dev/null @@ -1,14 +0,0 @@ -/*********************************************** -* User-space libc implementation header file -* Author: Jeffrey Tang -***********************************************/ - -// Terminates calling process -void exit(int status); - -// Yields to another (scheduler-determined) process -void proc_yield(); - -// Prints to stdout -int printf(const char *format, ...); - diff --git a/user/ulibc.s b/user/ulibc.s deleted file mode 100644 index 4891dfc5..00000000 --- a/user/ulibc.s +++ /dev/null @@ -1,23 +0,0 @@ -.global exit -.global yield -.global printf - -exit: - SVC 0 - MOV pc, lr - -; Need to save registers on the process stack -; since we can't rely on kernel to do it -yield: - PUSH {r0-r12,lr} - LDR r0, =resume ; pass resume addr to handler - LDR r1, sp ; pass sp to handler - ; these will be saved in PCB - SVC 1 -resume: - POP {r0-r12,pc} ; jump through lr to caller - -; Working state will be saved/restored by kernel -printf: - SVC 2 - MOV pc, lr