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