⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 erosimage.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 3 页
字号:
/* * 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 <assert.h>#include <sys/fcntl.h>#include <sys/stat.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <eros/target.h>#include <erosimg/Intern.hxx>#include <erosimg/ExecArch.hxx>#include <erosimg/ErosImage.hxx>#include <erosimg/Parse.hxx>#include <erosimg/App.hxx>#include <eros/Key.h>#include <eros/RangeKey.h>#include <eros/ProcessState.h>#include <disk/DiskNode.hxx>#include <disk/DiskLSS.hxx>/* Following is included as a special case so that AddProcess()   register conventions stay in sync with the expectations of the   runtime libraries. */#include "../../../lib/domain/include/domain/Runtime.h"#ifndef max#define max(x,y) ( ((x) > (y)) ? (x) : (y) )#endif#define PAGE_ALLOC_QUANTA 16#define NODE_ALLOC_QUANTA 16#define DIR_ALLOC_QUANTA 16#define THREAD_ALLOC_QUANTA 16extern void PrintDiskKey(const DiskKey&);static unsigned intGetAnyBlss(const DiskKey & key){  if (key.IsVoidKey()) return EROS_PAGE_BLSS;  return key.GetBlss();}ErosHeader::ErosHeader(){  /* First initialize the domain file image header: */    memset(signature, 0, 8);  strcpy(signature, "ErosImg");  imageByteSex = 0;  version = EROS_IMAGE_VERSION;  architecture = ExecArch::arch_unknown;  nDirEnt = 0;  nStartups = 0;  nPages = 0;  nZeroPages = 0;  nNodes = 0;  strSize = 0;  dirOffset = sizeof(ErosHeader);  startupsOffset = sizeof(ErosHeader);  pageOffset = sizeof(ErosHeader);  nodeOffset = sizeof(ErosHeader);  strTableOffset = sizeof(strTableOffset);}ErosImage::ErosImage(){  pageImages = 0;  nodeImages = 0;  dir = 0;  startupsDir = 0;  maxPage = 0;  maxNode = 0;  maxDir = 0;  maxStartups = 0;  DiskKey key = AddNode();  AddDirEnt("volsize", key);  key = AddNode();  AddDirEnt("threadlist", key);}ErosImage::~ErosImage(){  delete [] pageImages;  delete [] nodeImages;  delete [] dir;  delete [] startupsDir;}InternedStringErosImage::GetString(int ndx) const{  return InternedString(pool.Get(ndx));}boolErosImage::AddStartup(const char* name, const DiskKey& key){  InternedString is(name);  return AddStartup(is, key);}voidErosImage::AddDirEnt(const char* name, const DiskKey& key){  InternedString is(name);  AddDirEnt(is, key);}voidErosImage::AssignDirEnt(const char* name, const DiskKey& key){  InternedString is(name);  AssignDirEnt(is, key);}boolErosImage::AddStartup(const InternedString& name, const DiskKey& key){  uint32_t nameNdx = pool.Add(name);  if (key.IsType(KT_Process) || key.IsType(KT_Node)) {    if (GetProcessState(key) == RS_Waiting) {      Diag::printf("Attempt to re-start process that is already started.\n");      return false;    }    SetProcessState(key, RS_Waiting);  }  else if (key.IsType(KT_Start)) {    /* Arrangements should already have been made to get the target       process running, in which case it will be in the waiting state: */    if (GetProcessState(key) != RS_Waiting) {      Diag::printf("Attempt to invoke constructor that has not been started.\n");      return false;    }  }  else {    Diag::printf("Bad key type to AddThead()\n");    return false;  }  for (uint32_t i = 0; i < nStartups; i++)    if (startupsDir[i].name == nameNdx)      Diag::fatal(5, "Duplicate name \"%s\" added to image file\n", name.str());    if (nStartups >= maxStartups)    GrowStartupsTable(maxStartups + THREAD_ALLOC_QUANTA);  startupsDir[nStartups].key = key;  startupsDir[nStartups].name = nameNdx;  DiskKey threadChain;  assert ( GetDirEnt("threadlist", threadChain) );    for (unsigned i = 0; i < nStartups/(EROS_NODE_SIZE-1); i++)    threadChain = GetNodeSlot(threadChain, EROS_NODE_SIZE - 1);  unsigned ndx = nStartups % (EROS_NODE_SIZE - 1);  /* See if we need to append a new node: */   if ( nStartups && ndx == 0 ) {    DiskKey newNode = AddNode();    SetNodeSlot(threadChain, EROS_NODE_SIZE - 1, newNode);    SetDirEnt("threadlist", newNode);    threadChain = newNode;  }  SetNodeSlot(threadChain, ndx, key);  nStartups++;  return true;}voidErosImage::AddDirEnt(const InternedString& name, const DiskKey& key){  assert ( (bool) name );  assert (name.str() != 0);    uint32_t nameNdx = pool.Add(name);  for (uint32_t i = 0; i < nDirEnt; i++)    if (dir[i].name == nameNdx)      Diag::fatal(5, "Duplicate name \"%s\" added to image file\n", name.str());    if (nDirEnt >= maxDir)    GrowDirTable(maxDir + DIR_ALLOC_QUANTA);  dir[nDirEnt].key = key;  dir[nDirEnt].name = nameNdx;  nDirEnt++;}voidErosImage::AssignDirEnt(const InternedString& name, const DiskKey& key){  assert ( (bool) name );  assert (name.str() != 0);    uint32_t nameNdx = pool.Add(name);  for (uint32_t i = 0; i < nDirEnt; i++)    if (dir[i].name == nameNdx) {      dir[i].key = key;      return;    }    if (nDirEnt >= maxDir)    GrowDirTable(maxDir + DIR_ALLOC_QUANTA);  dir[nDirEnt].key = key;  dir[nDirEnt].name = nameNdx;  nDirEnt++;}boolErosImage::DelDirEnt(const char* name){  InternedString is(name);  return DelDirEnt(is);}boolErosImage::DelDirEnt(const InternedString& name){  assert ( (bool) name );  assert (name.str() != 0);    uint32_t nameNdx = pool.Add(name);  for (uint32_t i = 0; i < nDirEnt; i++) {    if (dir[i].name == nameNdx) {      for (uint32_t ent = i; ent < (nDirEnt - 1); ent++)	dir[ent] = dir[ent+1];      nDirEnt--;      return true;    }  }  return false;}boolErosImage::GetDirEnt(const char* name, DiskKey& key){  InternedString is(name);  return GetDirEnt(is, key);}boolErosImage::GetDirEnt(const InternedString& name, DiskKey& key){  uint32_t nameNdx = pool.Add(name);  for (uint32_t i = 0; i < nDirEnt; i++) {    if (dir[i].name == nameNdx) {      key = dir[i].key;      return true;    }  }  return false;}boolErosImage::GetStartupEnt(const char* name, DiskKey& key){  InternedString is(name);  return GetStartupEnt(is, key);}boolErosImage::GetStartupEnt(const InternedString& name, DiskKey& key){  uint32_t nameNdx = pool.Add(name);  for (uint32_t i = 0; i < nStartups; i++) {    if (startupsDir[i].name == nameNdx) {      key = startupsDir[i].key;      return true;    }  }  return false;}voidErosImage::SetDirEnt(const InternedString& name, const DiskKey& key){  uint32_t nameNdx = pool.Add(name);  for (uint32_t i = 0; i < nDirEnt; i++) {    if (dir[i].name == nameNdx) {      dir[i].key = key;      return;    }  }  Diag::fatal(1, "No directory entry for \"%s\"\n", name.str());}voidErosImage::GrowDirTable(uint32_t newMax){  if (maxDir < newMax) {    maxDir = newMax;    maxDir += (DIR_ALLOC_QUANTA - 1);    maxDir -= (maxDir % DIR_ALLOC_QUANTA);    Directory *newDir = new Directory[maxDir];    if (dir)      memcpy(newDir, dir, nDirEnt * sizeof(Directory));     delete [] dir;    dir = newDir;  }}voidErosImage::GrowStartupsTable(uint32_t newMax){  if (maxStartups < newMax) {    maxStartups = newMax;    maxStartups += (THREAD_ALLOC_QUANTA - 1);    maxStartups -= (maxStartups % THREAD_ALLOC_QUANTA);    Directory *newThreadDir = new Directory[maxDir];    if (startupsDir)      memcpy(newThreadDir, startupsDir, nStartups * sizeof(Directory));     delete [] startupsDir;    startupsDir = newThreadDir;  }}voidErosImage::GrowNodeTable(uint32_t newMax){  if (maxNode < newMax) {    maxNode = newMax;    maxNode += (NODE_ALLOC_QUANTA - 1);    maxNode -= (maxNode % NODE_ALLOC_QUANTA);    DiskNode *newNodeImages = new DiskNode[maxNode];    if (nodeImages)      memcpy(newNodeImages, nodeImages, nNodes * sizeof(DiskNode));     delete [] nodeImages;    nodeImages = newNodeImages;  }}voidErosImage::GrowPageTable(uint32_t newMax){  if (maxPage < newMax) {    maxPage = newMax;    maxPage += (PAGE_ALLOC_QUANTA - 1);    maxPage -= (maxPage % PAGE_ALLOC_QUANTA);    uint8_t *newPageImages = new uint8_t[maxPage * EROS_PAGE_SIZE];    if (pageImages)      memcpy(newPageImages, pageImages, nPages * EROS_PAGE_SIZE);     delete [] pageImages;    pageImages = newPageImages;  }}DiskKeyErosImage::AddZeroDataPage(bool readOnly){  OID oid(nZeroPages++);    DataPageKey key(oid, readOnly);  key.SetPrepared();  return key;}DiskKeyErosImage::AddDataPage(const uint8_t *buf, bool readOnly){  if (nPages >= maxPage)    GrowPageTable(maxPage + PAGE_ALLOC_QUANTA);  memcpy(&pageImages[nPages * EROS_PAGE_SIZE], buf, EROS_PAGE_SIZE);    OID  oid(nPages++);  DataPageKey key(oid, readOnly);  return key;}voidErosImage::GetDataPageContent(uint32_t ndx, uint8_t* buf){  if (ndx >= nPages)    Diag::fatal(5, "Not that many pages in image file\n");    memcpy(buf, &pageImages[ndx*EROS_PAGE_SIZE], EROS_PAGE_SIZE);}voidErosImage::GetNodeContent(uint32_t ndx, DiskNode& node){  if (ndx >= nNodes)    Diag::fatal(5, "Not that many nodes in image file\n");    memcpy(&node, &nodeImages[ndx], sizeof(DiskNode));}DiskKeyErosImage::AddNode(bool readOnly){  if (nNodes >= maxNode)    GrowNodeTable(maxNode + NODE_ALLOC_QUANTA);  DiskNode& node = nodeImages[nNodes];  OID  oid(nNodes++);  node.allocCount = 0;  node.callCount = 0;  node.oid = oid;  for (unsigned int i = 0; i < EROS_NODE_SIZE; i++)    node[i] = VoidDiskKey();  NodeKey key(oid, readOnly);  return key;}#if 0voidErosImage::Import(const ErosImage& image){  /* Step 1: Grow the various tables to hold the new entries: */  GrowDirTable(nDirEnt + image.nDirEnt);  GrowStartupsTable(nStartups + image.nStartups);  GrowPageTable(nPages + image.nPages);  GrowNodeTable(nNodes + image.nNodes-1);  /* Step 2: Append the other image's pages and nodes WITHOUT bumping   * our counts:   */    memcpy(&pageImages[nPages], image.pageImages,	 image.nPages * EROS_PAGE_SIZE);  /* Skip the first node, which is the volsize node: */  memcpy(&nodeImages[nNodes], image.nodeImages + 1,	 (image.nNodes - 1) * sizeof(DiskNode));  /* Step 3: Relocate the newly added nodes and directory entries: */  for (uint32_t ndx = 0; ndx < image.nNodes; ndx++) {    DiskNode& node = nodeImages[ndx + nNodes];    for (uint32_t slot = 0; slot < EROS_NODE_SIZE; slot++) {      DiskKey& key = node[slot];            /* If the key's OID needs to be adjusted, do so: */      if (key.IsType(KT_Page) && key.IsPrepared() == false)	key.unprep.oid += nPages;      else if (key.IsType(KT_Page) && key.IsPrepared())	key.unprep.oid += nZeroPages;      else if (key.IsNodeKeyType())	key.unprep.oid += (nNodes - 1);    }  }  /* Step 4: add the foreign directory table entries: */  for (uint32_t ndx = 0; ndx < image.nDirEnt; ndx++) {    Directory& dirEnt = image.dir[ndx];    DiskKey key = dirEnt.key;    /* Check the string table entry: */    InternedString name = image.GetString(dirEnt.name);    InternedString vs("volsize");        if (name == vs)      continue;        /* If the key's OID needs to be adjusted, do so: */    if (key.IsType(KT_Page) && key.IsPrepared() == false)      key.unprep.oid += nPages;    else if (key.IsType(KT_Page) && key.IsPrepared())      key.unprep.oid += nZeroPages;    else if (key.IsNodeKeyType())      key.unprep.oid += (nNodes - 1);    /* Add the resulting entry to our directory using the AddDirEnt

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -