The Pedigree Project 0.1
DiskImage.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "DiskImage.h"
21#include "pedigree/kernel/BootstrapInfo.h"
22#include "pedigree/kernel/LockGuard.h"
23#include "pedigree/kernel/Log.h"
24#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
25#include "pedigree/kernel/utilities/assert.h"
26#include "pedigree/kernel/utilities/utility.h"
27
28extern BootstrapStruct_t* g_pBootstrapInfo;
29
30DiskImage::~DiskImage() {
31 m_Cache.shutdown();
32}
33
34bool DiskImage::initialise() {
35 const BootstrapStruct_t::Module* modules = g_pBootstrapInfo->getModuleArray();
36 const size_t moduleCount = g_pBootstrapInfo->getModuleCount();
37 const BootstrapStruct_t::Module* image = nullptr;
38 for (size_t i = 0; i < moduleCount; ++i) {
39 const char* name = reinterpret_cast<const char*>(modules[i].name_ptr);
40 if (name && !StringCompare(name, "rootfs.img")) {
41 image = &modules[i];
42 break;
43 }
44 }
45
46 if (!image && moduleCount >= 2) {
47 image = &modules[1];
48 }
49 if (!image || image->end <= image->base) {
50 NOTICE("no root disk image found in boot modules");
51 return false;
52 }
53
54 uintptr_t baseAddress = image->base;
55 uintptr_t endAddress = image->end;
56
57 m_pBase = reinterpret_cast<void*>(baseAddress);
58 m_nSize = endAddress - baseAddress;
59 return true;
60}
61
62BufferView DiskImage::read(uint64_t location) {
63 LockGuard<Mutex> guard(m_CacheLock);
64 if ((location >= m_nSize) || !m_pBase) {
65 ERROR("DiskImage::read() - location " << location << " >= " << m_nSize);
66 ERROR(" -> or " << m_pBase << " is null");
67 return BufferView();
68 }
69
70 const size_t pageSize = PhysicalMemoryManager::getPageSize();
71 const uint64_t pageLocation = getPageLocation(location);
72 const uint64_t pageOffset = location - pageLocation;
73 if (location >= m_nSize || pageLocation >= m_nSize) {
74 return BufferView();
75 }
76 const size_t validLength =
77 pageSize < (m_nSize - pageLocation) ? pageSize : (m_nSize - pageLocation);
78
79 uintptr_t buffer = m_Cache.lookup(pageLocation);
80 if (buffer) {
81 return BufferView::fromAddress(buffer + pageOffset, validLength - pageOffset);
82 }
83
84 bool didExist = false;
85 buffer = m_Cache.insert(pageLocation, &didExist);
86 if (!buffer) {
87 return BufferView();
88 }
89 if (!didExist) {
90 ByteSet(reinterpret_cast<void*>(buffer), 0, pageSize);
91 MemoryCopy(reinterpret_cast<void*>(buffer), adjust_pointer(m_pBase, pageLocation), validLength);
92
93 m_Cache.markNoLongerEditing(pageLocation);
94 }
95
96 buffer = m_Cache.lookup(pageLocation);
97 return buffer ? BufferView::fromAddress(buffer + pageOffset, validLength - pageOffset)
98 : BufferView();
99}
100
101size_t DiskImage::getSize() const {
102 return m_nSize;
103}
104
105void DiskImage::align(uint64_t location) {
106 LockGuard<Mutex> guard(m_CacheLock);
107 for (size_t i = 0; i < m_nAlignPoints; ++i) {
108 if (m_AlignPoints[i] == location) {
109 return;
110 }
111 }
112
113 assert(m_nAlignPoints < 8);
114 m_AlignPoints[m_nAlignPoints++] = location;
115}
116
117bool DiskImage::pin(uint64_t location) {
118 LockGuard<Mutex> guard(m_CacheLock);
119 if (location >= m_nSize) {
120 return false;
121 }
122 return m_Cache.pin(getPageLocation(location));
123}
124
125void DiskImage::unpin(uint64_t location) {
126 LockGuard<Mutex> guard(m_CacheLock);
127 if (location >= m_nSize) {
128 return;
129 }
130 m_Cache.release(getPageLocation(location));
131}
132
133uint64_t DiskImage::getAlignmentPoint(uint64_t location) const {
134 uint64_t alignPoint = 0;
135 for (size_t i = 0; i < m_nAlignPoints; ++i) {
136 if (m_AlignPoints[i] <= location && m_AlignPoints[i] > alignPoint) {
137 alignPoint = m_AlignPoints[i];
138 }
139 }
140 return alignPoint;
141}
142
143uint64_t DiskImage::getPageLocation(uint64_t location) const {
144 const uint64_t alignPoint = getAlignmentPoint(location);
145 const size_t pageSize = PhysicalMemoryManager::getPageSize();
146 return location - ((location - alignPoint) % pageSize);
147}
void release(uintptr_t key)
Definition Cache.cc:1488
uintptr_t insert(uintptr_t key, bool *alreadyExisted=nullptr)
Definition Cache.cc:857
void markNoLongerEditing(uintptr_t key, size_t length=0)
Definition Cache.cc:2484
uintptr_t lookup(uintptr_t key)
Definition Cache.cc:709
bool shutdown()
Definition Cache.cc:654
MUST_USE_RESULT bool pin(uintptr_t key)
Definition Cache.cc:1462
virtual BufferView read(uint64_t location)
Definition DiskImage.cc:62
virtual void align(uint64_t location)
Sets the page boundary alignment after a specific location on the disk.
Definition DiskImage.cc:105
virtual size_t getSize() const
Gets the size of the disk.
Definition DiskImage.cc:101
virtual bool pin(uint64_t location)
Pins a cache page.
Definition DiskImage.cc:117
virtual void unpin(uint64_t location)
Definition DiskImage.cc:125
#define assert(x)
Definition assert.h:39