1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_TransferMemoryBlock.cpp
4
5 Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Rev: 46347 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/config.h>
17 #if NN_PLATFORM_HAS_MMU
18
19 #include <nn/svc.h>
20 #include <nn/util/util_Result.h>
21 #include <nn/os/os_Result.h>
22 #include <nn/os/os_TransferMemoryBlock.h>
23 #include <nn/os/os_SharedMemory.h>
24 #include <nn/os/os_MemoryMapSelect.h>
25 #include <nn/os/os_ErrorHandlerSelect.h>
26 #include "os_AddressSpaceManager.h"
27
28 namespace nn { namespace os {
29
Initialize(void * p,size_t size,bit32 myPermission,bit32 otherPermission)30 void TransferMemoryBlock::Initialize(
31 void* p,
32 size_t size,
33 bit32 myPermission,
34 bit32 otherPermission )
35 {
36 NN_OS_ERROR_IF_FAILED(TryInitialize(p, size, myPermission, otherPermission));
37 }
38
TryInitialize(void * p,size_t size,bit32 myPermission,bit32 otherPermission)39 Result TransferMemoryBlock::TryInitialize(
40 void* p,
41 size_t size,
42 bit32 myPermission,
43 bit32 otherPermission )
44 {
45 // Check that it is uninitialized.
46 NN_TASSERTMSG_( GetAddress() == NULL, "This TransferMemoryBlock instance has been already initialized.\n" );
47 if ( GetAddress() )
48 {
49 return ResultAlreadyInitialized();
50 }
51
52 // Check alignment.
53 if ( (reinterpret_cast<uptr>(p) % NN_OS_MEMORY_PAGE_SIZE ) != 0 )
54 {
55 return ResultMisalignedAddress();
56 }
57 if ( ( size % NN_OS_MEMORY_PAGE_SIZE ) != 0 )
58 {
59 return ResultMisalignedSize();
60 }
61
62 Handle handle;
63 Result result;
64 result = nn::svc::CreateMemoryBlock(&handle, reinterpret_cast<uptr>(p), size, myPermission, otherPermission);
65 NN_UTIL_RETURN_IF_FAILED(result);
66 this->SetHandle(handle);
67
68 SetAddressAndSize(reinterpret_cast<uptr>(p), size);
69 return result;
70 }
71
Finalize()72 void TransferMemoryBlock::Finalize()
73 {
74 if (this->IsValid())
75 {
76 Unmap();
77 this->HandleObject::Close();
78 }
79 }
80
81
82
83
AttachAndMap(Handle handle,size_t size,bit32 otherPermission,bit32 myPermission)84 Result TransferMemoryBlock::AttachAndMap(
85 Handle handle,
86 size_t size,
87 bit32 otherPermission,
88 bit32 myPermission )
89 {
90 // Check alignment.
91 if ( ( size % NN_OS_MEMORY_PAGE_SIZE ) != 0 )
92 {
93 return ResultMisalignedSize();
94 }
95
96 this->SetHandle(handle);
97 return Map(size, otherPermission, myPermission);
98 }
99
Map(size_t size,bit32 otherPermission,bit32 myPermission)100 Result TransferMemoryBlock::Map(
101 size_t size,
102 bit32 otherPermission,
103 bit32 myPermission )
104 {
105 // Check that it is uninitialized.
106 NN_TASSERT_( GetAddress() == NULL );
107 if ( GetAddress() )
108 {
109 return ResultAlreadyInitialized();
110 }
111
112 // Check alignment.
113 if ( ( size % NN_OS_MEMORY_PAGE_SIZE ) != 0 )
114 {
115 return ResultMisalignedSize();
116 }
117
118 // Get memory from the virtual address space.
119 uptr addr = os::detail::AllocateFromSharedMemorySpace(this, size);
120 if (addr == NULL)
121 {
122 return ResultNoAddressSpace();
123 }
124
125 this->MemoryBlockBase::SetReadOnly((myPermission & os::MEMORY_PERMISSION_WRITE) == 0);
126
127 Result result = nn::svc::MapMemoryBlock(GetHandle(), addr, myPermission, otherPermission);
128 if( result.IsFailure() )
129 {
130 os::detail::FreeToSharedMemorySpace(this);
131 return result;
132 }
133
134 m_SpaceAllocated = true;
135 return result;
136 }
137
Unmap()138 void TransferMemoryBlock::Unmap()
139 {
140 if (GetAddress() != NULL)
141 {
142 if( m_SpaceAllocated )
143 {
144 nn::svc::UnmapMemoryBlock(GetHandle(), GetAddress());
145 os::detail::FreeToSharedMemorySpace(this);
146 }
147 else
148 {
149 SetAddressAndSize(0, 0);
150 }
151 }
152 }
153
154
155 }}
156
157 #endif // if NN_PLATFORM_HAS_MMU
158