📄 mk_processtool.cxx
字号:
/* * Copyright (C) 1998, 1999, 2001, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <kerninc/kernel.hxx>#include <kerninc/Key.hxx>#include <kerninc/Invocation.hxx>#include <kerninc/Node.hxx>#include <kerninc/Thread.hxx>#include <eros/Key.h>#include <eros/Invoke.h>#include <eros/StdKeyType.h>#include <eros/ProcessToolKey.h>#include <eros/KeyBitsKey.h>/* CompareBrand(inv, pDomKey, pBrand) returns TRUE if the passed keys * were of the right type and it was feasible to compare their * brands. Otherwise, it returns FALSE. * * Iff CompareBrand returns TRUE, then it also updates inv.exit_w1 and * inv.exit_w2 to hold the capability type (start or resume) and the * key info field, respectively. */static boolCompareBrand(Invocation& inv, Key* pDomKey, Key* pBrand){ /* It was some sort of identify operation -- see if we can satisfy * it. Must not do this operation on prepared key, since the link * pointers mess things up rather badly. Since we know that these * are argument keys, the deprepare will not damage any state in the * client key registers. * * The brand slot never needs to be prepared anyway. */ /* WE NEED TO MAKE A TEMPORARY COPY OF THESE KEYS in case one of * them proves to be the output key. */ assert (pDomKey->IsPrepared()); pBrand->Prepare(); Node *domNode = (Node *) pDomKey->GetObjectPtr(); Key& otherBrand = (*domNode)[ProcBrand]; otherBrand.Prepare(); COMMIT_POINT(); /* Expensive comparison, primarily because we do not want to * unprepare the keys (unpreparing them would bump allocation counts * unnecessarily). */ if ( pBrand->GetType() != otherBrand.GetType() /* Do not compare flags field -- that is purely internal. */ || pBrand->keyData != otherBrand.keyData ) return false; /* If they *did* prepare, and they are object keys, then the object * pointers will be the same. */ if ( pBrand->IsObjectKey() ) { if (pBrand->ok.pObj != otherBrand.ok.pObj) return false; } else { if ( pBrand->keyData != pBrand->keyData || pBrand->nk.value[0] != otherBrand.nk.value[0] || pBrand->nk.value[1] != otherBrand.nk.value[1] || pBrand->nk.value[2] != otherBrand.nk.value[2] ) return false; } inv.exit.w1 = pDomKey->GetType(); inv.exit.w2 = pDomKey->keyData; /* Temporary keys of this form MUST NOT BE BUILT until after the * commit point!!! */ { /* Unchain, but do not unprepare -- the objects do not have on-disk * keys. */ Process *pContext = 0; if (pDomKey->IsGateKey()) pContext = pDomKey->gk.pContext; inv.SetExitKey(0, *pDomKey); if (inv.exit.pKey[0]) { assert (inv.exit.pKey[0]->IsPrepared()); inv.exit.pKey[0]->InitType(KT_Node); inv.exit.pKey[0]->SetPrepared(); /* We have really just copied the input key and smashed it for a * node key. We now have a prepared node key, UNLESS the input key * was actually a gate key, in which event we have a prepared node * key on the wrong keyring. Fix up the keyring in that case: */ if (pContext) { inv.exit.pKey[0]->NH_Unchain(); ObjectHeader *pObj = pContext->procRoot; assert (pObj); /* Link as next key after object */ inv.exit.pKey[0]->ok.pObj = pObj; inv.exit.pKey[0]->ok.next = pObj->kr.next; inv.exit.pKey[0]->ok.prev = (KeyRing *) pObj; pObj->kr.next = (KeyRing*) inv.exit.pKey[0]; inv.exit.pKey[0]->ok.next->prev = (KeyRing*) inv.exit.pKey[0]; } } } return true;}voidProcessToolKey(Invocation& inv){#if 0 Key& arg0Key = inv.entry.key[0]; /* user-provided key arg 0 */ Key& arg1Key = inv.entry.key[1]; /* user-provided brand key */ Key& domKey = arg0Key; /* key to domain */#endif /* Until proven otherwise: */ inv.exit.code = RC_RequestError; /* All of these operations return a single key, which is void until * proven otherwise: */ switch (inv.entry.code) { case OC_ProcTool_MkProcKey: { COMMIT_POINT(); if (inv.entry.key[0]->IsType(KT_Node) == false) {#if 0 dprintf(true, "domtool: entry key is not node key\n");#endif return; } if ( inv.entry.key[0]->IsReadOnly() ) {#if 0 printf("domtool: entry key is read only\n");#endif return; } if ( inv.entry.key[0]->IsNoCall() ) {#if 0 printf("domtool: entry key is no-call\n");#endif return; } assert ( inv.entry.key[0]->IsHazard() == false ); inv.exit.code = RC_OK; inv.SetExitKey(0, *inv.entry.key[0]); if (inv.exit.pKey[0]) { inv.exit.pKey[0]->SetType(KT_Process); inv.exit.pKey[0]->keyData = 0; } return; } case OC_ProcTool_IdentGateKey: { inv.entry.key[0]->Prepare(); if (inv.entry.key[0]->IsType(KT_Start) == false && inv.entry.key[0]->IsType(KT_Resume) == false) { COMMIT_POINT(); return; } bool isResume = inv.entry.key[0]->IsType(KT_Resume); inv.exit.code = RC_OK; if ( CompareBrand(inv, inv.entry.key[0], inv.entry.key[1]) == false ) return; /* brands do not match */ /* Must be either start or resume, by virtue of test above. */ inv.exit.w1 = (inv.exit.w1 == KT_Start) ? 1 : 2; if ( isResume ) inv.exit.w2 = inv.entry.key[0]->keyData; return; } case OC_ProcTool_IdentProcessKey: { inv.entry.key[0]->Prepare(); if (inv.entry.key[0]->IsType(KT_Process) == false) { COMMIT_POINT(); return; } inv.exit.code = RC_OK; if ( CompareBrand(inv, inv.entry.key[0], inv.entry.key[1]) ) { inv.exit.w1 = 1; inv.exit.w2 = 0; } return; } case OC_ProcTool_IdentSegGateKey: {#ifdef KT_Wrapper if (inv.entry.key[0]->IsType(KT_Wrapper) == false) { COMMIT_POINT(); return; }#else if (inv.entry.key[0]->IsType(KT_Segment) == false && inv.entry.key[0]->IsType(KT_Node) == false) { COMMIT_POINT(); return; } if (inv.entry.key[0]->IsRedSegmentKey() == false) { COMMIT_POINT(); return; }#endif if ( inv.entry.key[0]->IsNoCall() ) { COMMIT_POINT(); return; } inv.entry.key[0]->Prepare(); Node *theNode = (Node *) inv.entry.key[0]->GetObjectPtr();#ifdef KT_Wrapper Key& fmtKey = (*theNode)[WrapperFormat]; /* If no keeper key: */ if ((fmtKey.nk.value[0] & WRAPPER_KEEPER) == 0) { COMMIT_POINT(); return; } uint32_t slot = WrapperKeeper;#else Key& fmtKey = (*theNode)[RedSegFormat]; if ( fmtKey.IsValidFormatKey() == false ) {#if 0 extern void db_eros_print_key(Key&); db_eros_print_key(fmtKey); dprintf(true, "Bad format key!\n");#endif COMMIT_POINT(); return; } /* If no keeper key: */ uint32_t slot = REDSEG_GET_KPR_SLOT(fmtKey.nk); if ( slot == EROS_NODE_SLOT_MASK || (*theNode)[slot].IsGateKey() == false) { COMMIT_POINT(); return; }#endif Key& domKey = (*theNode)[slot]; domKey.Prepare(); if (domKey.IsType(KT_Start) == false && domKey.IsType(KT_Resume) == false) { COMMIT_POINT(); return; } bool isResume = domKey.IsType(KT_Resume); inv.exit.code = RC_OK; if ( CompareBrand(inv, &domKey, inv.entry.key[1]) == false ) return; /* Must be either start or resume, by virtue of test above. */ inv.exit.w1 = (inv.exit.w1 == KT_Start) ? 1 : 2; if ( isResume ) inv.exit.w2 = inv.entry.key[0]->keyData; return; } case OC_ProcTool_CompareProcessOrigins: { if ((inv.entry.key[0]->IsGateKey() == false) && (inv.entry.key[0]->IsType(KT_Process) == false)) { COMMIT_POINT(); return; } if ((inv.entry.key[1]->IsGateKey() == false) && (inv.entry.key[1]->IsType(KT_Process) == false)) { COMMIT_POINT(); return; } inv.entry.key[0]->Prepare(); inv.entry.key[1]->Prepare(); Node *domain0 = (Node *) inv.entry.key[0]->GetObjectPtr(); Node *domain1 = (Node *) inv.entry.key[1]->GetObjectPtr(); (*domain0)[ProcBrand].Prepare(); (*domain1)[ProcBrand].Prepare(); COMMIT_POINT(); Key& brand0 = (*domain0)[ProcBrand]; Key& brand1 = (*domain1)[ProcBrand]; inv.exit.code = RC_OK; /* The following works ONLY because neither the domain brand key nor * a key coming from a key register can be hazarded. */ if (memcmp( &brand0, &brand1, sizeof(Key)) == 0) inv.exit.w1 = 1; else inv.exit.w1 = 0; return; } case OC_KeyType: COMMIT_POINT(); inv.exit.code = RC_OK; inv.exit.w1 = inv.keyType; return; default: COMMIT_POINT(); inv.exit.code = RC_UnknownRequest; return; } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -