142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes/*
242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * Copyright (C) 2013 The Android Open Source Project
342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes *
442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * you may not use this file except in compliance with the License.
642b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * You may obtain a copy of the License at
742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes *
842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes *
1042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * Unless required by applicable law or agreed to in writing, software
1142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
1242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * See the License for the specific language governing permissions and
1442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * limitations under the License.
1542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes */
1642b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
1742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes#ifndef KERNEL_ARGUMENT_BLOCK_H
1842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes#define KERNEL_ARGUMENT_BLOCK_H
1942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
2042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes#include <elf.h>
2142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes#include <stdint.h>
2242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes#include <sys/auxv.h>
2342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
240d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesstruct abort_msg_t;
250d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes
2642b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes// When the kernel starts the dynamic linker, it passes a pointer to a block
2742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes// of memory containing argc, the argv array, the environment variable array,
2842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes// and the array of ELF aux vectors. This class breaks that block up into its
2942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes// constituents for easy access.
3042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughesclass KernelArgumentBlock {
3142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes public:
3242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  KernelArgumentBlock(void* raw_args) {
3342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    uint32_t* args = reinterpret_cast<uint32_t*>(raw_args);
3442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    argc = static_cast<int>(*args);
3542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    argv = reinterpret_cast<char**>(args + 1);
3642b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    envp = argv + argc + 1;
3742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
3842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    // Skip over all environment variable definitions to find aux vector.
3942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    // The end of the environment block is marked by two NULL pointers.
4042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    char** p = envp;
4142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    while (*p != NULL) {
4242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes      ++p;
4342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    }
4442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    ++p; // Skip second NULL;
4542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
4642b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    auxv = reinterpret_cast<Elf32_auxv_t*>(p);
4742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  }
4842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
4942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  // Similar to ::getauxval but doesn't require the libc global variables to be set up,
5042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  // so it's safe to call this really early on. This function also lets you distinguish
5142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  // between the inability to find the given type and its value just happening to be 0.
5242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  unsigned long getauxval(unsigned long type, bool* found_match = NULL) {
5342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    for (Elf32_auxv_t* v = auxv; v->a_type != AT_NULL; ++v) {
5442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes      if (v->a_type == type) {
5542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes        if (found_match != NULL) {
5642b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes            *found_match = true;
5742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes        }
5842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes        return v->a_un.a_val;
5942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes      }
6042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    }
6142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    if (found_match != NULL) {
6242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes      *found_match = false;
6342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    }
6442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    return 0;
6542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  }
6642b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
6742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  int argc;
6842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  char** argv;
6942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  char** envp;
7042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  Elf32_auxv_t* auxv;
7142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
720d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes  abort_msg_t** abort_message_ptr;
730d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes
7442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes private:
7542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  // Disallow copy and assignment.
7642b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  KernelArgumentBlock(const KernelArgumentBlock&);
7742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  void operator=(const KernelArgumentBlock&);
7842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes};
7942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
8042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes#endif // KERNEL_ARGUMENT_BLOCK_H
81