129a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi/*
229a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi * Copyright (C) 2016 The Android Open Source Project
329a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi *
429a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi * Licensed under the Apache License, Version 2.0 (the "License");
529a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi * you may not use this file except in compliance with the License.
629a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi * You may obtain a copy of the License at
729a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi *
829a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi *      http://www.apache.org/licenses/LICENSE-2.0
929a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi *
1029a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi * Unless required by applicable law or agreed to in writing, software
1129a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi * distributed under the License is distributed on an "AS IS" BASIS,
1229a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1329a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi * See the License for the specific language governing permissions and
1429a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi * limitations under the License.
1529a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi */
1629a28c40ccaa69b912f53e067b90a0ee3d7992dbAshutosh Joshi
1762b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg#include <syscall.h>
1862b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg#include <stdio.h>
1962b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
2062b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
2162b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
2262b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinbergstatic uint32_t mTableStore[(sizeof(struct SyscallTable) + sizeof(union SyscallTableEntry[1 << SYSCALL_BITS_LEVEL_0]) + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
2362b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinbergstatic const uint8_t mLevelBits[] = {SYSCALL_BITS_LEVEL_0, SYSCALL_BITS_LEVEL_1, SYSCALL_BITS_LEVEL_2, SYSCALL_BITS_LEVEL_3, 0};
2462b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinbergstatic struct SyscallTable *mTable = (struct SyscallTable*)mTableStore;
2562b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
2662b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
2762b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
2862b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinbergvoid syscallInit(void)
2962b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg{
3062b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    mTable->numEntries = 1 << SYSCALL_BITS_LEVEL_0;
3162b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg}
3262b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
3362b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinbergbool syscallAddTable(uint32_t path, uint32_t level, struct SyscallTable *table)
3462b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg{
3562b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    struct SyscallTable** tabP = &mTable;
3662b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    const uint8_t *bits = mLevelBits;
3762b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
3862b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    while (level--) {
3962b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg        uint32_t idx = path >> (32 - *bits);
4062b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg        path <<= *bits++;
4162b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
4262b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg        //cannot traverse
4362b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg        if ((*tabP)->numEntries <= idx)
4462b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg            return false;
4562b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
4662b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg        //cannot add table as final leaf
4762b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg        if (*bits == 0)
4862b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg            return false;
4962b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
5062b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg        tabP = &(*tabP)->entry[idx].subtable;
5162b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    }
5262b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
5362b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    *tabP = table;
5462b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    return true;
5562b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg}
5662b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
5762b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinbergstatic SyscallFunc* syscallFindHandlerLoc(uint32_t path)
5862b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg{
5962b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    struct SyscallTable* tab = mTable;
6062b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    const uint8_t *bits = mLevelBits;
6162b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
6262b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    while (tab) {
6362b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg        uint32_t idx = path >> (32 - *bits);
6462b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
6562b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg        path <<= *bits++;
6662b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
6762b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg        if (tab->numEntries <= idx)
6862b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg            break;
6962b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
700daf3debdabd99ceb38d372832c6b4dfcb3e1810Ben Fennema        if (!*bits)
7162b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg            return &tab->entry[idx].func;
7262b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg        else
7362b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg            tab = tab->entry[idx].subtable;
7462b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    }
7562b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
7662b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    return NULL;
7762b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg}
7862b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
7962b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinbergbool syscallAddFunc(uint32_t path, SyscallFunc func)
8062b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg{
8162b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    SyscallFunc *f = syscallFindHandlerLoc(path);
8262b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
8362b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    if (!f)
8462b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg        return false;
8562b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
8662b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    *f = func;
8762b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    return true;
8862b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg}
8962b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
9062b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry GrinbergSyscallFunc syscallGetHandler(uint32_t path)
9162b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg{
9262b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    SyscallFunc *f = syscallFindHandlerLoc(path);
9362b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg
9462b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg    return f ? *f : NULL;
9562b2b5d80e197210bfbe8dfb6aff66ccb8a495c1Dmitry Grinberg}
9674e472948470ccf63b9e80f4317f6b3eba8a194cDmitry Grinberg
9774e472948470ccf63b9e80f4317f6b3eba8a194cDmitry Grinberg
98