1 /* 2 * Program memory segment support. 3 * 4 * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <l4/sys/err.h> 23 24 #include <ipc/mem_ipc.h> 25 #include <mem/memory_utils.h> 26 27 #include <stdio.h> 28 #include <string.h> 29 30 #include "segment.h" 31 32 33 34 /* Obligatory destructor. */ 35 36 Segment::~Segment() 37 { 38 } 39 40 /* Common initialisation. */ 41 42 void Segment::init() 43 { 44 _region_base = trunc(region_address(), L4_PAGESIZE); 45 _region_content_offset = region_address() - _region_base; 46 47 /* Expand the region size. */ 48 49 _region_allocated_size = round(region_size() + _region_content_offset, L4_PAGESIZE); 50 } 51 52 /* Return the address of allocated memory. */ 53 54 char *Segment::address() 55 { 56 return _buf; 57 } 58 59 /* Return the size of the allocated memory. */ 60 61 offset_t Segment::size() 62 { 63 return _region_allocated_size; 64 } 65 66 /* Allocate a writable region for the segment. */ 67 68 long Segment::allocate() 69 { 70 return ipc_allocate_align(_region_allocated_size, L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RW, 71 L4_PAGESHIFT, (void **) &_buf, &_ds); 72 } 73 74 /* Fill a segment region with file content. */ 75 76 long Segment::fill(file_t *file) 77 { 78 /* Provide the exposed file contents in a masked memory mapped region. */ 79 80 _buf = (char *) client_mmap(file, 81 file_offset() - _region_content_offset, 82 _region_allocated_size, 83 file_offset(), 84 file_offset() + file_contents(), 85 region_flags()); 86 87 if (_buf == NULL) 88 return -L4_EIO; 89 else 90 return L4_EOK; 91 } 92 93 /* Define and return the mapped region for the segment. */ 94 95 MappedRegion &Segment::region() 96 { 97 _region = MappedRegion((l4_addr_t) _buf, _region_allocated_size, region_flags(), _region_base); 98 return _region; 99 } 100 101 /* Return the mapped address corresponding to the given address. */ 102 103 l4_addr_t Segment::region_address(char *address) 104 { 105 return (l4_addr_t) ((address - _buf) + (char *) _region_base); 106 } 107 108 l4_addr_t Segment::region_address(l4_addr_t address) 109 { 110 return (address - (l4_addr_t) _buf) + _region_base; 111 } 112 113 114 115 /* Initialise a memory segment using explicit parameters. */ 116 117 ExplicitSegment::ExplicitSegment(l4_addr_t base, offset_t size, 118 l4re_rm_flags_t flags, offset_t file_offset, 119 offset_t file_contents) 120 : _base(base), _size(size), _flags(flags), _file_offset(file_offset), 121 _file_contents(file_contents) 122 { 123 init(); 124 } 125 126 /* Return the amount of file content loaded into the segment. */ 127 128 bool ExplicitSegment::loadable() 129 { 130 return false; 131 } 132 133 offset_t ExplicitSegment::file_contents() 134 { 135 return _file_contents; 136 } 137 138 offset_t ExplicitSegment::file_offset() 139 { 140 return _file_offset; 141 } 142 143 l4_addr_t ExplicitSegment::region_address() 144 { 145 return _base; 146 } 147 148 offset_t ExplicitSegment::region_size() 149 { 150 return _size; 151 } 152 153 /* Return the region flags for the segment. */ 154 155 l4re_rm_flags_t ExplicitSegment::region_flags() 156 { 157 return _flags; 158 } 159 160 /* vim: tabstop=2 expandtab shiftwidth=2 161 */