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 /* Initialise a memory segment. */ 35 36 Segment::Segment(l4_addr_t base, offset_t size, l4re_rm_flags_t flags, 37 offset_t file_offset, offset_t file_contents) 38 39 : _base(base), _size(size), _flags(flags), _file_offset(file_offset), 40 _file_contents(file_contents) 41 { 42 _region_base = trunc(_base, L4_PAGESIZE); 43 _region_offset = _base - _region_base; 44 _region_size = round(_size, L4_PAGESIZE); 45 } 46 47 /* Return the address of allocated memory. */ 48 49 char *Segment::address() 50 { 51 return _buf; 52 } 53 54 /* Return the size of the allocated memory. */ 55 56 offset_t Segment::size() 57 { 58 return _size; 59 } 60 61 /* Allocate a region for the segment. */ 62 63 long Segment::allocate() 64 { 65 /* Make regions writable if they need to be filled. */ 66 67 l4re_rm_flags_t allocation_flags = _flags; 68 69 if (_file_contents) 70 allocation_flags |= L4RE_RM_F_W; 71 72 return ipc_allocate_align(_size, L4RE_RM_F_SEARCH_ADDR | allocation_flags, 73 L4_PAGESHIFT, (void **) &_buf, &_ds); 74 } 75 76 /* Fill a segment region with file content. */ 77 78 long Segment::fill(file_t *file) 79 { 80 if (!_file_contents) 81 return L4_EOK; 82 83 memset(_buf, 0, _region_size); 84 client_seek(file, _file_offset, SEEK_SET); 85 offset_t nread = client_read(file, _buf + _region_offset, _file_contents); 86 87 if (nread < _file_contents) 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, page_order(_region_size), _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 /* vim: tabstop=2 expandtab shiftwidth=2 114 */