1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_TransferMemoryBlock.cpp
4 
5   Copyright (C)2009 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: 29304 $
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_TransferMemoryBlock.h>
22 #include <nn/os/os_SharedMemory.h>
23 #include <nn/os/os_MemoryMapSelect.h>
24 #include <nn/err.h>
25 #include "os_AddressSpaceManager.h"
26 
27 namespace nn { namespace os {
28 
Initialize(void * p,size_t size,bit32 myPermission,bit32 otherPermission)29 void TransferMemoryBlock::Initialize(
30         void*   p,
31         size_t  size,
32         bit32   myPermission,
33         bit32   otherPermission )
34 {
35     // 未初期化であることをチェックします。
36     NN_TASSERT_( GetAddress() == NULL );
37     NN_ALIGN_TASSERT_( p, NN_OS_MEMORY_PAGE_SIZE );
38     NN_ALIGN_TASSERT_( size, NN_OS_MEMORY_PAGE_SIZE );
39 
40     Handle handle;
41     Result result;
42     result = nn::svc::CreateMemoryBlock(&handle, reinterpret_cast<uptr>(p), size, myPermission, otherPermission);
43     NN_ERR_THROW_FATAL(result);
44     this->SetHandle(handle);
45 
46     SetAddressAndSize(reinterpret_cast<uptr>(p), size);
47 }
48 
TryInitialize(void * p,size_t size,bit32 myPermission,bit32 otherPermission)49 Result TransferMemoryBlock::TryInitialize(
50         void*   p,
51         size_t  size,
52         bit32   myPermission,
53         bit32   otherPermission )
54 {
55     // 未初期化であることをチェックします。
56     NN_TASSERT_( GetAddress() == NULL );
57     NN_ALIGN_TASSERT_( p, NN_OS_MEMORY_PAGE_SIZE );
58     NN_ALIGN_TASSERT_( size, NN_OS_MEMORY_PAGE_SIZE );
59 
60     Handle handle;
61     Result result;
62     result = nn::svc::CreateMemoryBlock(&handle, reinterpret_cast<uptr>(p), size, myPermission, otherPermission);
63     NN_UTIL_RETURN_IF_FAILED(result);
64     this->SetHandle(handle);
65 
66     SetAddressAndSize(reinterpret_cast<uptr>(p), size);
67     return result;
68 }
69 
Finalize()70 void TransferMemoryBlock::Finalize()
71 {
72     if (this->IsValid())
73     {
74         Unmap();
75         this->HandleObject::Close();
76     }
77 }
78 
79 
80 
81 
AttachAndMap(Handle handle,size_t size,bit32 otherPermission,bit32 myPermission)82 Result TransferMemoryBlock::AttachAndMap(
83         Handle  handle,
84         size_t  size,
85         bit32   otherPermission,
86         bit32   myPermission )
87 {
88     NN_ALIGN_TASSERT_( size, NN_OS_MEMORY_PAGE_SIZE );
89 
90     this->SetHandle(handle);
91     return Map(size, otherPermission, myPermission);
92 }
93 
Map(size_t size,bit32 otherPermission,bit32 myPermission)94 Result TransferMemoryBlock::Map(
95         size_t  size,
96         bit32   otherPermission,
97         bit32   myPermission )
98 {
99     // 未初期化であることをチェックします。
100     NN_TASSERT_( GetAddress() == NULL );
101     NN_ALIGN_TASSERT_( size, NN_OS_MEMORY_PAGE_SIZE );
102 
103     // 仮想アドレス空間からメモリを取得します。
104     uptr addr = detail::AllocateFromSharedMemorySpace(this, size);
105     if (addr == NULL)
106     {
107         NN_TPANIC_("failed to allocate address space.");
108     }
109 
110     this->MemoryBlockBase::SetReadOnly((myPermission & os::MEMORY_PERMISSION_WRITE) == 0);
111 
112     Result result = nn::svc::MapMemoryBlock(GetHandle(), addr, myPermission, otherPermission);
113     if( result.IsFailure() )
114     {
115         return result;
116     }
117 
118     m_SpaceAllocated = true;
119     return result;
120 }
121 
Unmap()122 void TransferMemoryBlock::Unmap()
123 {
124     if (GetAddress() != NULL)
125     {
126         if( m_SpaceAllocated )
127         {
128             nn::svc::UnmapMemoryBlock(GetHandle(), GetAddress());
129             detail::FreeToSharedMemorySpace(this);
130         }
131         else
132         {
133             SetAddressAndSize(0, 0);
134         }
135     }
136 }
137 
138 
139 }}
140 
141 #endif  // if NN_PLATFORM_HAS_MMU
142