disk_image.cc revision 8232
111988Sandreas.sandberg@arm.com/*
28839Sandreas.hansson@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan
38839Sandreas.hansson@arm.com * All rights reserved.
48839Sandreas.hansson@arm.com *
58839Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68839Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
78839Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
88839Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
98839Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
108839Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
118839Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
128839Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
133101Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from
148579Ssteve.reinhardt@amd.com * this software without specific prior written permission.
153101Sstever@eecs.umich.edu *
163101Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173101Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183101Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193101Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203101Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213101Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223101Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233101Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243101Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253101Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263101Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273101Sstever@eecs.umich.edu *
283101Sstever@eecs.umich.edu * Authors: Nathan Binkert
293101Sstever@eecs.umich.edu */
303101Sstever@eecs.umich.edu
313101Sstever@eecs.umich.edu/** @file
323101Sstever@eecs.umich.edu * Disk Image Definitions
333101Sstever@eecs.umich.edu */
343101Sstever@eecs.umich.edu
353101Sstever@eecs.umich.edu#include <sys/types.h>
363101Sstever@eecs.umich.edu#include <sys/uio.h>
373101Sstever@eecs.umich.edu#include <unistd.h>
383101Sstever@eecs.umich.edu
393101Sstever@eecs.umich.edu#include <cerrno>
403101Sstever@eecs.umich.edu#include <cstring>
413101Sstever@eecs.umich.edu#include <fstream>
427778Sgblack@eecs.umich.edu#include <string>
438839Sandreas.hansson@arm.com
443101Sstever@eecs.umich.edu#include "base/callback.hh"
453101Sstever@eecs.umich.edu#include "base/misc.hh"
463101Sstever@eecs.umich.edu#include "base/trace.hh"
473101Sstever@eecs.umich.edu#include "debug/DiskImageRead.hh"
483101Sstever@eecs.umich.edu#include "debug/DiskImageWrite.hh"
493101Sstever@eecs.umich.edu#include "dev/disk_image.hh"
503101Sstever@eecs.umich.edu#include "sim/byteswap.hh"
513101Sstever@eecs.umich.edu#include "sim/sim_exit.hh"
523101Sstever@eecs.umich.edu
533101Sstever@eecs.umich.eduusing namespace std;
543101Sstever@eecs.umich.edu
553101Sstever@eecs.umich.edu////////////////////////////////////////////////////////////////////////
563101Sstever@eecs.umich.edu//
573101Sstever@eecs.umich.edu// Raw Disk image
583101Sstever@eecs.umich.edu//
593101Sstever@eecs.umich.eduRawDiskImage::RawDiskImage(const Params* p)
603101Sstever@eecs.umich.edu    : DiskImage(p), disk_size(0)
613101Sstever@eecs.umich.edu{ open(p->image_file, p->read_only); }
6212563Sgabeblack@google.com
6312563Sgabeblack@google.comRawDiskImage::~RawDiskImage()
643885Sbinkertn@umich.edu{ close(); }
653885Sbinkertn@umich.edu
664762Snate@binkert.orgvoid
673885Sbinkertn@umich.eduRawDiskImage::open(const string &filename, bool rd_only)
683885Sbinkertn@umich.edu{
697528Ssteve.reinhardt@amd.com    if (!filename.empty()) {
703885Sbinkertn@umich.edu        initialized = true;
714380Sbinkertn@umich.edu        readonly = rd_only;
724167Sbinkertn@umich.edu        file = filename;
733102Sstever@eecs.umich.edu
743101Sstever@eecs.umich.edu        ios::openmode mode = ios::in | ios::binary;
754762Snate@binkert.org        if (!readonly)
764762Snate@binkert.org            mode |= ios::out;
774762Snate@binkert.org        stream.open(file.c_str(), mode);
784762Snate@binkert.org        if (!stream.is_open())
794762Snate@binkert.org            panic("Error opening %s", filename);
804762Snate@binkert.org    }
814762Snate@binkert.org}
824762Snate@binkert.org
834762Snate@binkert.orgvoid
845033Smilesck@eecs.umich.eduRawDiskImage::close()
855033Smilesck@eecs.umich.edu{
865033Smilesck@eecs.umich.edu    stream.close();
875033Smilesck@eecs.umich.edu}
885033Smilesck@eecs.umich.edu
895033Smilesck@eecs.umich.eduoff_t
905033Smilesck@eecs.umich.eduRawDiskImage::size() const
915033Smilesck@eecs.umich.edu{
925033Smilesck@eecs.umich.edu    if (disk_size == 0) {
935033Smilesck@eecs.umich.edu        if (!stream.is_open())
943101Sstever@eecs.umich.edu            panic("file not open!\n");
953101Sstever@eecs.umich.edu        stream.seekg(0, ios::end);
963101Sstever@eecs.umich.edu        disk_size = stream.tellg();
975033Smilesck@eecs.umich.edu    }
9810267SGeoffrey.Blake@arm.com
998596Ssteve.reinhardt@amd.com    return disk_size / SectorSize;
1008596Ssteve.reinhardt@amd.com}
1018596Ssteve.reinhardt@amd.com
1028596Ssteve.reinhardt@amd.comoff_t
1037673Snate@binkert.orgRawDiskImage::read(uint8_t *data, off_t offset) const
1047673Snate@binkert.org{
1057673Snate@binkert.org    if (!initialized)
1067673Snate@binkert.org        panic("RawDiskImage not initialized");
10711988Sandreas.sandberg@arm.com
10811988Sandreas.sandberg@arm.com    if (!stream.is_open())
10911988Sandreas.sandberg@arm.com        panic("file not open!\n");
11011988Sandreas.sandberg@arm.com
1113101Sstever@eecs.umich.edu    if (stream.seekg(offset * SectorSize, ios::beg) < 0)
1123101Sstever@eecs.umich.edu        panic("Could not seek to location in file");
1133101Sstever@eecs.umich.edu
1143101Sstever@eecs.umich.edu    streampos pos = stream.tellg();
1153101Sstever@eecs.umich.edu    stream.read((char *)data, SectorSize);
11610380SAndrew.Bardsley@arm.com
11710380SAndrew.Bardsley@arm.com    DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
11810380SAndrew.Bardsley@arm.com    DDUMP(DiskImageRead, data, SectorSize);
11910380SAndrew.Bardsley@arm.com
12010380SAndrew.Bardsley@arm.com    return stream.tellg() - pos;
12110380SAndrew.Bardsley@arm.com}
12210458Sandreas.hansson@arm.com
12310458Sandreas.hansson@arm.comoff_t
12410458Sandreas.hansson@arm.comRawDiskImage::write(const uint8_t *data, off_t offset)
12510458Sandreas.hansson@arm.com{
12610458Sandreas.hansson@arm.com    if (!initialized)
12710458Sandreas.hansson@arm.com        panic("RawDiskImage not initialized");
12810458Sandreas.hansson@arm.com
12910458Sandreas.hansson@arm.com    if (readonly)
13010458Sandreas.hansson@arm.com        panic("Cannot write to a read only disk image");
13110458Sandreas.hansson@arm.com
13210458Sandreas.hansson@arm.com    if (!stream.is_open())
13310458Sandreas.hansson@arm.com        panic("file not open!\n");
1343101Sstever@eecs.umich.edu
1353101Sstever@eecs.umich.edu    if (stream.seekp(offset * SectorSize, ios::beg) < 0)
1363101Sstever@eecs.umich.edu        panic("Could not seek to location in file");
1373101Sstever@eecs.umich.edu
1383101Sstever@eecs.umich.edu    DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
13910267SGeoffrey.Blake@arm.com    DDUMP(DiskImageWrite, data, SectorSize);
14010267SGeoffrey.Blake@arm.com
14110267SGeoffrey.Blake@arm.com    streampos pos = stream.tellp();
14210267SGeoffrey.Blake@arm.com    stream.write((const char *)data, SectorSize);
1433101Sstever@eecs.umich.edu    return stream.tellp() - pos;
1443101Sstever@eecs.umich.edu}
1453101Sstever@eecs.umich.edu
1463101Sstever@eecs.umich.eduRawDiskImage *
1473101Sstever@eecs.umich.eduRawDiskImageParams::create()
1483101Sstever@eecs.umich.edu{
1493101Sstever@eecs.umich.edu    return new RawDiskImage(this);
1503101Sstever@eecs.umich.edu}
1513101Sstever@eecs.umich.edu
1523101Sstever@eecs.umich.edu////////////////////////////////////////////////////////////////////////
1533101Sstever@eecs.umich.edu//
1543101Sstever@eecs.umich.edu// Copy on Write Disk image
1553101Sstever@eecs.umich.edu//
1563101Sstever@eecs.umich.educonst uint32_t CowDiskImage::VersionMajor = 1;
1573101Sstever@eecs.umich.educonst uint32_t CowDiskImage::VersionMinor = 0;
1583101Sstever@eecs.umich.edu
1593101Sstever@eecs.umich.educlass CowDiskCallback : public Callback
1603101Sstever@eecs.umich.edu{
1613101Sstever@eecs.umich.edu  private:
1623101Sstever@eecs.umich.edu    CowDiskImage *image;
1633101Sstever@eecs.umich.edu
1643101Sstever@eecs.umich.edu  public:
1653101Sstever@eecs.umich.edu    CowDiskCallback(CowDiskImage *i) : image(i) {}
1663101Sstever@eecs.umich.edu    void process() { image->save(); delete this; }
1673101Sstever@eecs.umich.edu};
1683101Sstever@eecs.umich.edu
1693101Sstever@eecs.umich.eduCowDiskImage::CowDiskImage(const Params *p)
1703101Sstever@eecs.umich.edu    : DiskImage(p), filename(p->image_file), child(p->child), table(NULL)
1713101Sstever@eecs.umich.edu{
1723101Sstever@eecs.umich.edu    if (filename.empty()) {
1733101Sstever@eecs.umich.edu        init(p->table_size);
1743101Sstever@eecs.umich.edu    } else {
1753101Sstever@eecs.umich.edu        if (!open(filename)) {
1763101Sstever@eecs.umich.edu            if (p->read_only)
1773101Sstever@eecs.umich.edu                fatal("could not open read-only file");
1785033Smilesck@eecs.umich.edu            init(p->table_size);
1796656Snate@binkert.org        }
1805033Smilesck@eecs.umich.edu
1815033Smilesck@eecs.umich.edu        if (!p->read_only)
1825033Smilesck@eecs.umich.edu            registerExitCallback(new CowDiskCallback(this));
1833101Sstever@eecs.umich.edu    }
1843101Sstever@eecs.umich.edu}
1853101Sstever@eecs.umich.edu
18610267SGeoffrey.Blake@arm.comCowDiskImage::~CowDiskImage()
18710267SGeoffrey.Blake@arm.com{
18810267SGeoffrey.Blake@arm.com    SectorTable::iterator i = table->begin();
18910267SGeoffrey.Blake@arm.com    SectorTable::iterator end = table->end();
19010267SGeoffrey.Blake@arm.com
19110267SGeoffrey.Blake@arm.com    while (i != end) {
19210267SGeoffrey.Blake@arm.com        delete (*i).second;
19310267SGeoffrey.Blake@arm.com        ++i;
19410267SGeoffrey.Blake@arm.com    }
19510267SGeoffrey.Blake@arm.com}
19610267SGeoffrey.Blake@arm.com
19710267SGeoffrey.Blake@arm.comvoid
19810267SGeoffrey.Blake@arm.comSafeRead(ifstream &stream, void *data, int count)
1993101Sstever@eecs.umich.edu{
2003101Sstever@eecs.umich.edu    stream.read((char *)data, count);
2013101Sstever@eecs.umich.edu    if (!stream.is_open())
2023101Sstever@eecs.umich.edu        panic("file not open");
2033101Sstever@eecs.umich.edu
2043101Sstever@eecs.umich.edu    if (stream.eof())
2053101Sstever@eecs.umich.edu        panic("premature end-of-file");
2063101Sstever@eecs.umich.edu
2073101Sstever@eecs.umich.edu    if (stream.bad() || stream.fail())
2083101Sstever@eecs.umich.edu        panic("error reading cowdisk image");
2093102Sstever@eecs.umich.edu}
2103101Sstever@eecs.umich.edu
2113101Sstever@eecs.umich.edutemplate<class T>
2123101Sstever@eecs.umich.eduvoid
21310267SGeoffrey.Blake@arm.comSafeRead(ifstream &stream, T &data)
21410267SGeoffrey.Blake@arm.com{
21510267SGeoffrey.Blake@arm.com    SafeRead(stream, &data, sizeof(data));
21610267SGeoffrey.Blake@arm.com}
21710267SGeoffrey.Blake@arm.com
21810267SGeoffrey.Blake@arm.comtemplate<class T>
21910267SGeoffrey.Blake@arm.comvoid
2207673Snate@binkert.orgSafeReadSwap(ifstream &stream, T &data)
2218607Sgblack@eecs.umich.edu{
2227673Snate@binkert.org    SafeRead(stream, &data, sizeof(data));
2233101Sstever@eecs.umich.edu    data = letoh(data); //is this the proper byte order conversion?
22411988Sandreas.sandberg@arm.com}
22511988Sandreas.sandberg@arm.com
22611988Sandreas.sandberg@arm.combool
2277673Snate@binkert.orgCowDiskImage::open(const string &file)
2287673Snate@binkert.org{
2293101Sstever@eecs.umich.edu    ifstream stream(file.c_str());
2303101Sstever@eecs.umich.edu    if (!stream.is_open())
2313101Sstever@eecs.umich.edu        return false;
2323101Sstever@eecs.umich.edu
2333101Sstever@eecs.umich.edu    if (stream.fail() || stream.bad())
2343101Sstever@eecs.umich.edu        panic("Error opening %s", file);
2355033Smilesck@eecs.umich.edu
2365475Snate@binkert.org    uint64_t magic;
2375475Snate@binkert.org    SafeRead(stream, magic);
2385475Snate@binkert.org
2395475Snate@binkert.org    if (memcmp(&magic, "COWDISK!", sizeof(magic)) != 0)
24010380SAndrew.Bardsley@arm.com        panic("Could not open %s: Invalid magic", file);
24110380SAndrew.Bardsley@arm.com
24210380SAndrew.Bardsley@arm.com    uint32_t major, minor;
2433101Sstever@eecs.umich.edu    SafeReadSwap(stream, major);
2443101Sstever@eecs.umich.edu    SafeReadSwap(stream, minor);
2453101Sstever@eecs.umich.edu
2464762Snate@binkert.org    if (major != VersionMajor && minor != VersionMinor)
2474762Snate@binkert.org        panic("Could not open %s: invalid version %d.%d != %d.%d",
2484762Snate@binkert.org              file, major, minor, VersionMajor, VersionMinor);
2493101Sstever@eecs.umich.edu
25012050Snikos.nikoleris@arm.com    uint64_t sector_count;
25112050Snikos.nikoleris@arm.com    SafeReadSwap(stream, sector_count);
25212050Snikos.nikoleris@arm.com    table = new SectorTable(sector_count);
2538459SAli.Saidi@ARM.com
2548459SAli.Saidi@ARM.com
25512050Snikos.nikoleris@arm.com    for (uint64_t i = 0; i < sector_count; i++) {
2563101Sstever@eecs.umich.edu        uint64_t offset;
2577528Ssteve.reinhardt@amd.com        SafeReadSwap(stream, offset);
2587528Ssteve.reinhardt@amd.com
2597528Ssteve.reinhardt@amd.com        Sector *sector = new Sector;
2607528Ssteve.reinhardt@amd.com        SafeRead(stream, sector, sizeof(Sector));
2617528Ssteve.reinhardt@amd.com
2627528Ssteve.reinhardt@amd.com        assert(table->find(offset) == table->end());
2633101Sstever@eecs.umich.edu        (*table)[offset] = sector;
2647528Ssteve.reinhardt@amd.com    }
2657528Ssteve.reinhardt@amd.com
2667528Ssteve.reinhardt@amd.com    stream.close();
2677528Ssteve.reinhardt@amd.com
2687528Ssteve.reinhardt@amd.com    initialized = true;
2697528Ssteve.reinhardt@amd.com    return true;
2707528Ssteve.reinhardt@amd.com}
2717528Ssteve.reinhardt@amd.com
2727528Ssteve.reinhardt@amd.comvoid
2737528Ssteve.reinhardt@amd.comCowDiskImage::init(int hash_size)
2748321Ssteve.reinhardt@amd.com{
27512194Sgabeblack@google.com    table = new SectorTable(hash_size);
2767528Ssteve.reinhardt@amd.com
2777528Ssteve.reinhardt@amd.com    initialized = true;
2787528Ssteve.reinhardt@amd.com}
2797528Ssteve.reinhardt@amd.com
2807528Ssteve.reinhardt@amd.comvoid
2817528Ssteve.reinhardt@amd.comSafeWrite(ofstream &stream, const void *data, int count)
2827528Ssteve.reinhardt@amd.com{
2837528Ssteve.reinhardt@amd.com    stream.write((const char *)data, count);
2847528Ssteve.reinhardt@amd.com    if (!stream.is_open())
2857528Ssteve.reinhardt@amd.com        panic("file not open");
2867528Ssteve.reinhardt@amd.com
2877528Ssteve.reinhardt@amd.com    if (stream.eof())
2887528Ssteve.reinhardt@amd.com        panic("premature end-of-file");
2893101Sstever@eecs.umich.edu
2908664SAli.Saidi@ARM.com    if (stream.bad() || stream.fail())
2918664SAli.Saidi@ARM.com        panic("error reading cowdisk image");
2928664SAli.Saidi@ARM.com}
2938664SAli.Saidi@ARM.com
2948664SAli.Saidi@ARM.comtemplate<class T>
2958664SAli.Saidi@ARM.comvoid
2969953Sgeoffrey.blake@arm.comSafeWrite(ofstream &stream, const T &data)
2979953Sgeoffrey.blake@arm.com{
2989953Sgeoffrey.blake@arm.com    SafeWrite(stream, &data, sizeof(data));
2999953Sgeoffrey.blake@arm.com}
3009953Sgeoffrey.blake@arm.com
3019953Sgeoffrey.blake@arm.comtemplate<class T>
3029953Sgeoffrey.blake@arm.comvoid
3039953Sgeoffrey.blake@arm.comSafeWriteSwap(ofstream &stream, const T &data)
3049953Sgeoffrey.blake@arm.com{
3059953Sgeoffrey.blake@arm.com    T swappeddata = letoh(data); //is this the proper byte order conversion?
3069953Sgeoffrey.blake@arm.com    SafeWrite(stream, &swappeddata, sizeof(data));
3079953Sgeoffrey.blake@arm.com}
3089953Sgeoffrey.blake@arm.comvoid
30910267SGeoffrey.Blake@arm.comCowDiskImage::save()
31010267SGeoffrey.Blake@arm.com{
31110267SGeoffrey.Blake@arm.com    save(filename);
31210267SGeoffrey.Blake@arm.com}
31310267SGeoffrey.Blake@arm.com
31410267SGeoffrey.Blake@arm.comvoid
31510267SGeoffrey.Blake@arm.comCowDiskImage::save(const string &file)
31612563Sgabeblack@google.com{
31710267SGeoffrey.Blake@arm.com    if (!initialized)
31810267SGeoffrey.Blake@arm.com        panic("RawDiskImage not initialized");
31910267SGeoffrey.Blake@arm.com
32010267SGeoffrey.Blake@arm.com    ofstream stream(file.c_str());
32110267SGeoffrey.Blake@arm.com    if (!stream.is_open() || stream.fail() || stream.bad())
32210267SGeoffrey.Blake@arm.com        panic("Error opening %s", file);
32310267SGeoffrey.Blake@arm.com
32410267SGeoffrey.Blake@arm.com    uint64_t magic;
32510267SGeoffrey.Blake@arm.com    memcpy(&magic, "COWDISK!", sizeof(magic));
32610267SGeoffrey.Blake@arm.com    SafeWrite(stream, magic);
32710267SGeoffrey.Blake@arm.com
32810267SGeoffrey.Blake@arm.com    SafeWriteSwap(stream, (uint32_t)VersionMajor);
3293101Sstever@eecs.umich.edu    SafeWriteSwap(stream, (uint32_t)VersionMinor);
3303101Sstever@eecs.umich.edu    SafeWriteSwap(stream, (uint64_t)table->size());
3313101Sstever@eecs.umich.edu
3323101Sstever@eecs.umich.edu    uint64_t size = table->size();
3333101Sstever@eecs.umich.edu    SectorTable::iterator iter = table->begin();
3343101Sstever@eecs.umich.edu    SectorTable::iterator end = table->end();
3353101Sstever@eecs.umich.edu
33610364SGeoffrey.Blake@arm.com    for (uint64_t i = 0; i < size; i++) {
33710364SGeoffrey.Blake@arm.com        if (iter == end)
33810364SGeoffrey.Blake@arm.com            panic("Incorrect Table Size during save of COW disk image");
33910364SGeoffrey.Blake@arm.com
3403101Sstever@eecs.umich.edu        SafeWriteSwap(stream, (uint64_t)(*iter).first);
3414762Snate@binkert.org        SafeWrite(stream, (*iter).second->data, sizeof(Sector));
3424762Snate@binkert.org        ++iter;
3434762Snate@binkert.org    }
3444762Snate@binkert.org
3457528Ssteve.reinhardt@amd.com    stream.close();
3464762Snate@binkert.org}
3474762Snate@binkert.org
3484762Snate@binkert.orgvoid
34910267SGeoffrey.Blake@arm.comCowDiskImage::writeback()
35010267SGeoffrey.Blake@arm.com{
35110267SGeoffrey.Blake@arm.com    SectorTable::iterator i = table->begin();
35210267SGeoffrey.Blake@arm.com    SectorTable::iterator end = table->end();
35310267SGeoffrey.Blake@arm.com
35410267SGeoffrey.Blake@arm.com    while (i != end) {
35510267SGeoffrey.Blake@arm.com        child->write((*i).second->data, (*i).first);
35610267SGeoffrey.Blake@arm.com        ++i;
35710267SGeoffrey.Blake@arm.com    }
35810267SGeoffrey.Blake@arm.com}
35910267SGeoffrey.Blake@arm.com
36010267SGeoffrey.Blake@arm.comoff_t
36110267SGeoffrey.Blake@arm.comCowDiskImage::size() const
36210267SGeoffrey.Blake@arm.com{ return child->size(); }
36310267SGeoffrey.Blake@arm.com
36410267SGeoffrey.Blake@arm.comoff_t
36510267SGeoffrey.Blake@arm.comCowDiskImage::read(uint8_t *data, off_t offset) const
36610267SGeoffrey.Blake@arm.com{
36710267SGeoffrey.Blake@arm.com    if (!initialized)
36810267SGeoffrey.Blake@arm.com        panic("CowDiskImage not initialized");
36910267SGeoffrey.Blake@arm.com
37010267SGeoffrey.Blake@arm.com    if (offset > size())
37110267SGeoffrey.Blake@arm.com        panic("access out of bounds");
37210267SGeoffrey.Blake@arm.com
37310267SGeoffrey.Blake@arm.com    SectorTable::const_iterator i = table->find(offset);
37410267SGeoffrey.Blake@arm.com    if (i == table->end())
37510364SGeoffrey.Blake@arm.com        return child->read(data, offset);
37610364SGeoffrey.Blake@arm.com    else {
37710267SGeoffrey.Blake@arm.com        memcpy(data, (*i).second->data, SectorSize);
37810267SGeoffrey.Blake@arm.com        DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
37910267SGeoffrey.Blake@arm.com        DDUMP(DiskImageRead, data, SectorSize);
38010267SGeoffrey.Blake@arm.com        return SectorSize;
38110267SGeoffrey.Blake@arm.com    }
38210267SGeoffrey.Blake@arm.com}
3837673Snate@binkert.org
3847673Snate@binkert.orgoff_t
3857673Snate@binkert.orgCowDiskImage::write(const uint8_t *data, off_t offset)
3863101Sstever@eecs.umich.edu{
38711988Sandreas.sandberg@arm.com    if (!initialized)
38811988Sandreas.sandberg@arm.com        panic("RawDiskImage not initialized");
38911988Sandreas.sandberg@arm.com
39011988Sandreas.sandberg@arm.com    if (offset > size())
3917673Snate@binkert.org        panic("access out of bounds");
3927673Snate@binkert.org
3933101Sstever@eecs.umich.edu    SectorTable::iterator i = table->find(offset);
3943101Sstever@eecs.umich.edu    if (i == table->end()) {
3953101Sstever@eecs.umich.edu        Sector *sector = new Sector;
3963101Sstever@eecs.umich.edu        memcpy(sector, data, SectorSize);
3973101Sstever@eecs.umich.edu        table->insert(make_pair(offset, sector));
3983101Sstever@eecs.umich.edu    } else {
3993101Sstever@eecs.umich.edu        memcpy((*i).second->data, data, SectorSize);
4003101Sstever@eecs.umich.edu    }
4013101Sstever@eecs.umich.edu
4023101Sstever@eecs.umich.edu    DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
4033101Sstever@eecs.umich.edu    DDUMP(DiskImageWrite, data, SectorSize);
4043101Sstever@eecs.umich.edu
4053101Sstever@eecs.umich.edu    return SectorSize;
4063101Sstever@eecs.umich.edu}
4073101Sstever@eecs.umich.edu
4085033Smilesck@eecs.umich.eduvoid
4095033Smilesck@eecs.umich.eduCowDiskImage::serialize(ostream &os)
4103101Sstever@eecs.umich.edu{
4113101Sstever@eecs.umich.edu    string cowFilename = name() + ".cow";
4123101Sstever@eecs.umich.edu    SERIALIZE_SCALAR(cowFilename);
4133101Sstever@eecs.umich.edu    save(Checkpoint::dir() + "/" + cowFilename);
4143101Sstever@eecs.umich.edu}
4153101Sstever@eecs.umich.edu
4163101Sstever@eecs.umich.eduvoid
4173101Sstever@eecs.umich.eduCowDiskImage::unserialize(Checkpoint *cp, const string &section)
4183101Sstever@eecs.umich.edu{
4193101Sstever@eecs.umich.edu    string cowFilename;
4203101Sstever@eecs.umich.edu    UNSERIALIZE_SCALAR(cowFilename);
4213101Sstever@eecs.umich.edu    cowFilename = cp->cptDir + "/" + cowFilename;
4223101Sstever@eecs.umich.edu    open(cowFilename);
4233101Sstever@eecs.umich.edu}
4243101Sstever@eecs.umich.edu
4253101Sstever@eecs.umich.eduCowDiskImage *
4263101Sstever@eecs.umich.eduCowDiskImageParams::create()
4273101Sstever@eecs.umich.edu{
4283101Sstever@eecs.umich.edu    return new CowDiskImage(this);
4293101Sstever@eecs.umich.edu}
4303101Sstever@eecs.umich.edu