disk_image.cc revision 9637
16019Shines@cs.fsu.edu/*
212495Sgiacomo.travaglini@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan
37111Sgblack@eecs.umich.edu * All rights reserved.
47111Sgblack@eecs.umich.edu *
57111Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67111Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77111Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87111Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97111Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107111Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117111Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127111Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137111Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
146019Shines@cs.fsu.edu * this software without specific prior written permission.
156019Shines@cs.fsu.edu *
166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276019Shines@cs.fsu.edu *
286019Shines@cs.fsu.edu * Authors: Nathan Binkert
296019Shines@cs.fsu.edu */
306019Shines@cs.fsu.edu
316019Shines@cs.fsu.edu/** @file
326019Shines@cs.fsu.edu * Disk Image Definitions
336019Shines@cs.fsu.edu */
346019Shines@cs.fsu.edu
356019Shines@cs.fsu.edu#include <sys/types.h>
366019Shines@cs.fsu.edu#include <sys/uio.h>
376019Shines@cs.fsu.edu#include <unistd.h>
386019Shines@cs.fsu.edu
396019Shines@cs.fsu.edu#include <cerrno>
406019Shines@cs.fsu.edu#include <cstring>
416019Shines@cs.fsu.edu#include <fstream>
426019Shines@cs.fsu.edu#include <string>
436019Shines@cs.fsu.edu
446019Shines@cs.fsu.edu#include "base/callback.hh"
456019Shines@cs.fsu.edu#include "base/misc.hh"
466019Shines@cs.fsu.edu#include "base/trace.hh"
476019Shines@cs.fsu.edu#include "debug/DiskImageRead.hh"
487692SAli.Saidi@ARM.com#include "debug/DiskImageWrite.hh"
496242Sgblack@eecs.umich.edu#include "dev/disk_image.hh"
506019Shines@cs.fsu.edu#include "sim/byteswap.hh"
5112334Sgabeblack@google.com#include "sim/sim_exit.hh"
527408Sgblack@eecs.umich.edu
536216Snate@binkert.orgusing namespace std;
547720Sgblack@eecs.umich.edu
556019Shines@cs.fsu.edu////////////////////////////////////////////////////////////////////////
566019Shines@cs.fsu.edu//
5710037SARM gem5 Developers// Raw Disk image
5810037SARM gem5 Developers//
596019Shines@cs.fsu.eduRawDiskImage::RawDiskImage(const Params* p)
606019Shines@cs.fsu.edu    : DiskImage(p), disk_size(0)
617751SAli.Saidi@ARM.com{ open(p->image_file, p->read_only); }
627751SAli.Saidi@ARM.com
637751SAli.Saidi@ARM.comRawDiskImage::~RawDiskImage()
647751SAli.Saidi@ARM.com{ close(); }
657751SAli.Saidi@ARM.com
667751SAli.Saidi@ARM.comvoid
677751SAli.Saidi@ARM.comRawDiskImage::open(const string &filename, bool rd_only)
687751SAli.Saidi@ARM.com{
697751SAli.Saidi@ARM.com    if (!filename.empty()) {
708303SAli.Saidi@ARM.com        initialized = true;
717751SAli.Saidi@ARM.com        readonly = rd_only;
728303SAli.Saidi@ARM.com        file = filename;
738303SAli.Saidi@ARM.com
748303SAli.Saidi@ARM.com        ios::openmode mode = ios::in | ios::binary;
757751SAli.Saidi@ARM.com        if (!readonly)
767720Sgblack@eecs.umich.edu            mode |= ios::out;
778303SAli.Saidi@ARM.com        stream.open(file.c_str(), mode);
788303SAli.Saidi@ARM.com        if (!stream.is_open())
798303SAli.Saidi@ARM.com            panic("Error opening %s", filename);
808303SAli.Saidi@ARM.com    }
818303SAli.Saidi@ARM.com}
828303SAli.Saidi@ARM.com
838303SAli.Saidi@ARM.comvoid
848303SAli.Saidi@ARM.comRawDiskImage::close()
858303SAli.Saidi@ARM.com{
868303SAli.Saidi@ARM.com    stream.close();
878303SAli.Saidi@ARM.com}
888303SAli.Saidi@ARM.com
898303SAli.Saidi@ARM.comstd::streampos
908303SAli.Saidi@ARM.comRawDiskImage::size() const
917751SAli.Saidi@ARM.com{
927751SAli.Saidi@ARM.com    if (disk_size == 0) {
937751SAli.Saidi@ARM.com        if (!stream.is_open())
947751SAli.Saidi@ARM.com            panic("file not open!\n");
957720Sgblack@eecs.umich.edu        stream.seekg(0, ios::end);
967751SAli.Saidi@ARM.com        disk_size = stream.tellg();
977720Sgblack@eecs.umich.edu    }
987751SAli.Saidi@ARM.com
997751SAli.Saidi@ARM.com    return disk_size / SectorSize;
1007751SAli.Saidi@ARM.com}
1017751SAli.Saidi@ARM.com
1027751SAli.Saidi@ARM.comstd::streampos
1037751SAli.Saidi@ARM.comRawDiskImage::read(uint8_t *data, std::streampos offset) const
1046242Sgblack@eecs.umich.edu{
1057751SAli.Saidi@ARM.com    if (!initialized)
1067751SAli.Saidi@ARM.com        panic("RawDiskImage not initialized");
10710407Smitch.hayenga@arm.com
1087751SAli.Saidi@ARM.com    if (!stream.is_open())
1096019Shines@cs.fsu.edu        panic("file not open!\n");
1107751SAli.Saidi@ARM.com
1116246Sgblack@eecs.umich.edu    stream.seekg(offset * SectorSize, ios::beg);
1127751SAli.Saidi@ARM.com    if (!stream.good())
1137751SAli.Saidi@ARM.com        panic("Could not seek to location in file");
1147751SAli.Saidi@ARM.com
1157751SAli.Saidi@ARM.com    streampos pos = stream.tellg();
1167751SAli.Saidi@ARM.com    stream.read((char *)data, SectorSize);
1176329Sgblack@eecs.umich.edu
1187751SAli.Saidi@ARM.com    DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
1196757SAli.Saidi@ARM.com    DDUMP(DiskImageRead, data, SectorSize);
1207751SAli.Saidi@ARM.com
1217751SAli.Saidi@ARM.com    return stream.tellg() - pos;
1227751SAli.Saidi@ARM.com}
12310037SARM gem5 Developers
1247751SAli.Saidi@ARM.comstd::streampos
1257638Sgblack@eecs.umich.eduRawDiskImage::write(const uint8_t *data, std::streampos offset)
1267751SAli.Saidi@ARM.com{
1277751SAli.Saidi@ARM.com    if (!initialized)
1287751SAli.Saidi@ARM.com        panic("RawDiskImage not initialized");
1297751SAli.Saidi@ARM.com
1307751SAli.Saidi@ARM.com    if (readonly)
1317638Sgblack@eecs.umich.edu        panic("Cannot write to a read only disk image");
1327751SAli.Saidi@ARM.com
1337751SAli.Saidi@ARM.com    if (!stream.is_open())
1347751SAli.Saidi@ARM.com        panic("file not open!\n");
1357751SAli.Saidi@ARM.com
1367751SAli.Saidi@ARM.com    stream.seekp(offset * SectorSize, ios::beg);
1377638Sgblack@eecs.umich.edu    if (!stream.good())
1387751SAli.Saidi@ARM.com        panic("Could not seek to location in file");
1397751SAli.Saidi@ARM.com
1407751SAli.Saidi@ARM.com    DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
1417751SAli.Saidi@ARM.com    DDUMP(DiskImageWrite, data, SectorSize);
1427751SAli.Saidi@ARM.com
1436757SAli.Saidi@ARM.com    streampos pos = stream.tellp();
14410037SARM gem5 Developers    stream.write((const char *)data, SectorSize);
14510037SARM gem5 Developers    return stream.tellp() - pos;
14610037SARM gem5 Developers}
14710037SARM gem5 Developers
1487751SAli.Saidi@ARM.comRawDiskImage *
14910037SARM gem5 DevelopersRawDiskImageParams::create()
15010037SARM gem5 Developers{
1517751SAli.Saidi@ARM.com    return new RawDiskImage(this);
1527640Sgblack@eecs.umich.edu}
15310037SARM gem5 Developers
15410037SARM gem5 Developers////////////////////////////////////////////////////////////////////////
1557751SAli.Saidi@ARM.com//
15610037SARM gem5 Developers// Copy on Write Disk image
15710037SARM gem5 Developers//
1587751SAli.Saidi@ARM.comconst uint32_t CowDiskImage::VersionMajor = 1;
1597640Sgblack@eecs.umich.educonst uint32_t CowDiskImage::VersionMinor = 0;
16012496Sgiacomo.travaglini@arm.com
16112496Sgiacomo.travaglini@arm.comclass CowDiskCallback : public Callback
16212496Sgiacomo.travaglini@arm.com{
16312496Sgiacomo.travaglini@arm.com  private:
16412496Sgiacomo.travaglini@arm.com    CowDiskImage *image;
16512496Sgiacomo.travaglini@arm.com
16612496Sgiacomo.travaglini@arm.com  public:
16712496Sgiacomo.travaglini@arm.com    CowDiskCallback(CowDiskImage *i) : image(i) {}
16812496Sgiacomo.travaglini@arm.com    void process() { image->save(); delete this; }
16912496Sgiacomo.travaglini@arm.com};
17012496Sgiacomo.travaglini@arm.com
17112496Sgiacomo.travaglini@arm.comCowDiskImage::CowDiskImage(const Params *p)
17212496Sgiacomo.travaglini@arm.com    : DiskImage(p), filename(p->image_file), child(p->child), table(NULL)
17312496Sgiacomo.travaglini@arm.com{
17412496Sgiacomo.travaglini@arm.com    if (filename.empty()) {
17512496Sgiacomo.travaglini@arm.com        initSectorTable(p->table_size);
17612496Sgiacomo.travaglini@arm.com    } else {
17712496Sgiacomo.travaglini@arm.com        if (!open(filename)) {
17812494Schuan.zhu@arm.com            if (p->read_only)
17912494Schuan.zhu@arm.com                fatal("could not open read-only file");
18010037SARM gem5 Developers            initSectorTable(p->table_size);
18110037SARM gem5 Developers        }
18213759Sgiacomo.gabrielli@arm.com
18313759Sgiacomo.gabrielli@arm.com        if (!p->read_only)
18413759Sgiacomo.gabrielli@arm.com            registerExitCallback(new CowDiskCallback(this));
18513759Sgiacomo.gabrielli@arm.com    }
18613759Sgiacomo.gabrielli@arm.com}
18713759Sgiacomo.gabrielli@arm.com
18810037SARM gem5 DevelopersCowDiskImage::~CowDiskImage()
18910037SARM gem5 Developers{
19012788Sgiacomo.travaglini@arm.com    SectorTable::iterator i = table->begin();
19112788Sgiacomo.travaglini@arm.com    SectorTable::iterator end = table->end();
19212788Sgiacomo.travaglini@arm.com
19312788Sgiacomo.travaglini@arm.com    while (i != end) {
19412788Sgiacomo.travaglini@arm.com        delete (*i).second;
19512788Sgiacomo.travaglini@arm.com        ++i;
19612788Sgiacomo.travaglini@arm.com    }
19712788Sgiacomo.travaglini@arm.com}
19812788Sgiacomo.travaglini@arm.com
19912788Sgiacomo.travaglini@arm.comvoid
20012788Sgiacomo.travaglini@arm.comSafeRead(ifstream &stream, void *data, int count)
20112788Sgiacomo.travaglini@arm.com{
20212788Sgiacomo.travaglini@arm.com    stream.read((char *)data, count);
20312788Sgiacomo.travaglini@arm.com    if (!stream.is_open())
20412788Sgiacomo.travaglini@arm.com        panic("file not open");
20512788Sgiacomo.travaglini@arm.com
20612788Sgiacomo.travaglini@arm.com    if (stream.eof())
20712788Sgiacomo.travaglini@arm.com        panic("premature end-of-file");
20812788Sgiacomo.travaglini@arm.com
20912788Sgiacomo.travaglini@arm.com    if (stream.bad() || stream.fail())
21011514Sandreas.sandberg@arm.com        panic("error reading cowdisk image");
21111514Sandreas.sandberg@arm.com}
21211514Sandreas.sandberg@arm.com
21311514Sandreas.sandberg@arm.comtemplate<class T>
21411514Sandreas.sandberg@arm.comvoid
21511514Sandreas.sandberg@arm.comSafeRead(ifstream &stream, T &data)
21611514Sandreas.sandberg@arm.com{
21711514Sandreas.sandberg@arm.com    SafeRead(stream, &data, sizeof(data));
21811514Sandreas.sandberg@arm.com}
21911514Sandreas.sandberg@arm.com
22010037SARM gem5 Developerstemplate<class T>
22110037SARM gem5 Developersvoid
22210037SARM gem5 DevelopersSafeReadSwap(ifstream &stream, T &data)
22310037SARM gem5 Developers{
22410037SARM gem5 Developers    SafeRead(stream, &data, sizeof(data));
22510037SARM gem5 Developers    data = letoh(data); //is this the proper byte order conversion?
22610037SARM gem5 Developers}
22710854SNathanael.Premillieu@arm.com
22810854SNathanael.Premillieu@arm.combool
22910037SARM gem5 DevelopersCowDiskImage::open(const string &file)
23010037SARM gem5 Developers{
2317751SAli.Saidi@ARM.com    ifstream stream(file.c_str());
23210037SARM gem5 Developers    if (!stream.is_open())
2337751SAli.Saidi@ARM.com        return false;
23410037SARM gem5 Developers
23510037SARM gem5 Developers    if (stream.fail() || stream.bad())
23610037SARM gem5 Developers        panic("Error opening %s", file);
23710037SARM gem5 Developers
23810037SARM gem5 Developers    uint64_t magic;
23910037SARM gem5 Developers    SafeRead(stream, magic);
24010037SARM gem5 Developers
24110037SARM gem5 Developers    if (memcmp(&magic, "COWDISK!", sizeof(magic)) != 0)
24210037SARM gem5 Developers        panic("Could not open %s: Invalid magic", file);
24310037SARM gem5 Developers
24410037SARM gem5 Developers    uint32_t major, minor;
24510037SARM gem5 Developers    SafeReadSwap(stream, major);
2467751SAli.Saidi@ARM.com    SafeReadSwap(stream, minor);
2477640Sgblack@eecs.umich.edu
24812495Sgiacomo.travaglini@arm.com    if (major != VersionMajor && minor != VersionMinor)
24912495Sgiacomo.travaglini@arm.com        panic("Could not open %s: invalid version %d.%d != %d.%d",
25012495Sgiacomo.travaglini@arm.com              file, major, minor, VersionMajor, VersionMinor);
25112495Sgiacomo.travaglini@arm.com
25212495Sgiacomo.travaglini@arm.com    uint64_t sector_count;
25312495Sgiacomo.travaglini@arm.com    SafeReadSwap(stream, sector_count);
25412495Sgiacomo.travaglini@arm.com    table = new SectorTable(sector_count);
25512495Sgiacomo.travaglini@arm.com
25612495Sgiacomo.travaglini@arm.com
25710037SARM gem5 Developers    for (uint64_t i = 0; i < sector_count; i++) {
25810037SARM gem5 Developers        uint64_t offset;
25913550Sgiacomo.travaglini@arm.com        SafeReadSwap(stream, offset);
26013550Sgiacomo.travaglini@arm.com
26113550Sgiacomo.travaglini@arm.com        Sector *sector = new Sector;
26213585Sgabeblack@google.com        SafeRead(stream, sector, sizeof(Sector));
26313550Sgiacomo.travaglini@arm.com
26413550Sgiacomo.travaglini@arm.com        assert(table->find(offset) == table->end());
26513585Sgabeblack@google.com        (*table)[offset] = sector;
26610037SARM gem5 Developers    }
26710037SARM gem5 Developers
26810037SARM gem5 Developers    stream.close();
26910037SARM gem5 Developers
27010037SARM gem5 Developers    initialized = true;
27110037SARM gem5 Developers    return true;
27210037SARM gem5 Developers}
27310037SARM gem5 Developers
27410037SARM gem5 Developersvoid
27510037SARM gem5 DevelopersCowDiskImage::initSectorTable(int hash_size)
27610037SARM gem5 Developers{
27710037SARM gem5 Developers    table = new SectorTable(hash_size);
27810037SARM gem5 Developers
27910037SARM gem5 Developers    initialized = true;
28010037SARM gem5 Developers}
28110037SARM gem5 Developers
28210037SARM gem5 Developersvoid
28310037SARM gem5 DevelopersSafeWrite(ofstream &stream, const void *data, int count)
28410037SARM gem5 Developers{
28510037SARM gem5 Developers    stream.write((const char *)data, count);
28610037SARM gem5 Developers    if (!stream.is_open())
28710037SARM gem5 Developers        panic("file not open");
28810037SARM gem5 Developers
28910037SARM gem5 Developers    if (stream.eof())
29010037SARM gem5 Developers        panic("premature end-of-file");
29110037SARM gem5 Developers
29210037SARM gem5 Developers    if (stream.bad() || stream.fail())
29310037SARM gem5 Developers        panic("error reading cowdisk image");
29410037SARM gem5 Developers}
29510037SARM gem5 Developers
29610037SARM gem5 Developerstemplate<class T>
29710037SARM gem5 Developersvoid
29810037SARM gem5 DevelopersSafeWrite(ofstream &stream, const T &data)
29910037SARM gem5 Developers{
30010037SARM gem5 Developers    SafeWrite(stream, &data, sizeof(data));
30110037SARM gem5 Developers}
30210037SARM gem5 Developers
30310037SARM gem5 Developerstemplate<class T>
30410037SARM gem5 Developersvoid
30510037SARM gem5 DevelopersSafeWriteSwap(ofstream &stream, const T &data)
30610037SARM gem5 Developers{
30710037SARM gem5 Developers    T swappeddata = letoh(data); //is this the proper byte order conversion?
30810037SARM gem5 Developers    SafeWrite(stream, &swappeddata, sizeof(data));
30910037SARM gem5 Developers}
31010037SARM gem5 Developersvoid
31110037SARM gem5 DevelopersCowDiskImage::save()
31210037SARM gem5 Developers{
31310037SARM gem5 Developers    save(filename);
31410037SARM gem5 Developers}
31510037SARM gem5 Developers
31613999Sgiacomo.travaglini@arm.comvoid
31713999Sgiacomo.travaglini@arm.comCowDiskImage::save(const string &file)
31810037SARM gem5 Developers{
31910037SARM gem5 Developers    if (!initialized)
32010037SARM gem5 Developers        panic("RawDiskImage not initialized");
32110037SARM gem5 Developers
32210037SARM gem5 Developers    ofstream stream(file.c_str());
32310037SARM gem5 Developers    if (!stream.is_open() || stream.fail() || stream.bad())
32410037SARM gem5 Developers        panic("Error opening %s", file);
32510037SARM gem5 Developers
32610037SARM gem5 Developers    uint64_t magic;
3277707Sgblack@eecs.umich.edu    memcpy(&magic, "COWDISK!", sizeof(magic));
3286757SAli.Saidi@ARM.com    SafeWrite(stream, magic);
3297693SAli.Saidi@ARM.com
3307693SAli.Saidi@ARM.com    SafeWriteSwap(stream, (uint32_t)VersionMajor);
3317720Sgblack@eecs.umich.edu    SafeWriteSwap(stream, (uint32_t)VersionMinor);
33210417Sandreas.hansson@arm.com    SafeWriteSwap(stream, (uint64_t)table->size());
3337720Sgblack@eecs.umich.edu
3347720Sgblack@eecs.umich.edu    uint64_t size = table->size();
3357720Sgblack@eecs.umich.edu    SectorTable::iterator iter = table->begin();
3367720Sgblack@eecs.umich.edu    SectorTable::iterator end = table->end();
3377752SWilliam.Wang@arm.com
3387752SWilliam.Wang@arm.com    for (uint64_t i = 0; i < size; i++) {
3397752SWilliam.Wang@arm.com        if (iter == end)
3408300Schander.sudanthi@arm.com            panic("Incorrect Table Size during save of COW disk image");
3418300Schander.sudanthi@arm.com
3428300Schander.sudanthi@arm.com        SafeWriteSwap(stream, (uint64_t)(*iter).first);
3438300Schander.sudanthi@arm.com        SafeWrite(stream, (*iter).second->data, sizeof(Sector));
3448300Schander.sudanthi@arm.com        ++iter;
3458300Schander.sudanthi@arm.com    }
34610037SARM gem5 Developers
34710037SARM gem5 Developers    stream.close();
34810037SARM gem5 Developers}
34910037SARM gem5 Developers
35010037SARM gem5 Developersvoid
35110037SARM gem5 DevelopersCowDiskImage::writeback()
35210037SARM gem5 Developers{
35310037SARM gem5 Developers    SectorTable::iterator i = table->begin();
35410037SARM gem5 Developers    SectorTable::iterator end = table->end();
35510037SARM gem5 Developers
35610037SARM gem5 Developers    while (i != end) {
35710037SARM gem5 Developers        child->write((*i).second->data, (*i).first);
35810037SARM gem5 Developers        ++i;
35910037SARM gem5 Developers    }
36010037SARM gem5 Developers}
36110037SARM gem5 Developers
36210037SARM gem5 Developersstd::streampos
36310037SARM gem5 DevelopersCowDiskImage::size() const
36410037SARM gem5 Developers{ return child->size(); }
36510037SARM gem5 Developers
36610037SARM gem5 Developersstd::streampos
36710037SARM gem5 DevelopersCowDiskImage::read(uint8_t *data, std::streampos offset) const
36810037SARM gem5 Developers{
36910037SARM gem5 Developers    if (!initialized)
37010037SARM gem5 Developers        panic("CowDiskImage not initialized");
37110037SARM gem5 Developers
37210037SARM gem5 Developers    if (offset > size())
37310037SARM gem5 Developers        panic("access out of bounds");
37410037SARM gem5 Developers
37510037SARM gem5 Developers    SectorTable::const_iterator i = table->find(offset);
37612526Schuan.zhu@arm.com    if (i == table->end())
37712526Schuan.zhu@arm.com        return child->read(data, offset);
37812526Schuan.zhu@arm.com    else {
37912526Schuan.zhu@arm.com        memcpy(data, (*i).second->data, SectorSize);
38012526Schuan.zhu@arm.com        DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
3818902Sandreas.hansson@arm.com        DDUMP(DiskImageRead, data, SectorSize);
3826019Shines@cs.fsu.edu        return SectorSize;
3836019Shines@cs.fsu.edu    }
384}
385
386std::streampos
387CowDiskImage::write(const uint8_t *data, std::streampos offset)
388{
389    if (!initialized)
390        panic("RawDiskImage not initialized");
391
392    if (offset > size())
393        panic("access out of bounds");
394
395    SectorTable::iterator i = table->find(offset);
396    if (i == table->end()) {
397        Sector *sector = new Sector;
398        memcpy(sector, data, SectorSize);
399        table->insert(make_pair(offset, sector));
400    } else {
401        memcpy((*i).second->data, data, SectorSize);
402    }
403
404    DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
405    DDUMP(DiskImageWrite, data, SectorSize);
406
407    return SectorSize;
408}
409
410void
411CowDiskImage::serialize(ostream &os)
412{
413    string cowFilename = name() + ".cow";
414    SERIALIZE_SCALAR(cowFilename);
415    save(Checkpoint::dir() + "/" + cowFilename);
416}
417
418void
419CowDiskImage::unserialize(Checkpoint *cp, const string &section)
420{
421    string cowFilename;
422    UNSERIALIZE_SCALAR(cowFilename);
423    cowFilename = cp->cptDir + "/" + cowFilename;
424    open(cowFilename);
425}
426
427CowDiskImage *
428CowDiskImageParams::create()
429{
430    return new CowDiskImage(this);
431}
432