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: 38846 $
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 = 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         return result;
131     }
132 
133     m_SpaceAllocated = true;
134     return result;
135 }
136 
Unmap()137 void TransferMemoryBlock::Unmap()
138 {
139     if (GetAddress() != NULL)
140     {
141         if( m_SpaceAllocated )
142         {
143             nn::svc::UnmapMemoryBlock(GetHandle(), GetAddress());
144             detail::FreeToSharedMemorySpace(this);
145         }
146         else
147         {
148             SetAddressAndSize(0, 0);
149         }
150     }
151 }
152 
153 
154 }}
155 
156 #endif  // if NN_PLATFORM_HAS_MMU
157