iPXE
segment.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 /**
27  * @file
28  *
29  * Executable image segments
30  *
31  */
32 
33 #include <string.h>
34 #include <errno.h>
35 #include <ipxe/uaccess.h>
36 #include <ipxe/memmap.h>
37 #include <ipxe/errortab.h>
38 #include <ipxe/segment.h>
39 
40 /**
41  * Segment-specific error messages
42  *
43  * This error happens sufficiently often to merit a user-friendly
44  * description.
45  */
46 #define ERANGE_SEGMENT __einfo_error ( EINFO_ERANGE_SEGMENT )
47 #define EINFO_ERANGE_SEGMENT \
48  __einfo_uniqify ( EINFO_ERANGE, 0x01, "Requested memory not available" )
49 struct errortab segment_errors[] __errortab = {
51 };
52 
53 /**
54  * Prepare segment for loading
55  *
56  * @v segment Segment start
57  * @v filesz Size of the "allocated bytes" portion of the segment
58  * @v memsz Size of the segment
59  * @ret rc Return status code
60  */
61 int prep_segment ( void *segment, size_t filesz, size_t memsz ) {
62  struct memmap_region region;
63  physaddr_t start = virt_to_phys ( segment );
64  physaddr_t mid = ( start + filesz );
65  physaddr_t end = ( start + memsz );
67 
68  DBGC ( segment, "SEGMENT [%#08lx,%#08lx,%#08lx)\n", start, mid, end );
69 
70  /* Check for malformed lengths */
71  if ( filesz > memsz ) {
72  DBGC ( segment, "SEGMENT [%#08lx,%#08lx,%#08lx) is "
73  "malformed\n", start, mid, end );
74  return -EINVAL;
75  }
76 
77  /* Zero-length segments do not need a memory region */
78  if ( memsz == 0 )
79  return 0;
80  max = ( end - 1 );
81 
82  /* Check for address space overflow */
83  if ( max < start ) {
84  DBGC ( segment, "SEGMENT [%#08lx,%#08lx,%#08lx) wraps "
85  "around\n", start, mid, end );
86  return -EINVAL;
87  }
88 
89  /* Describe region containing this segment */
90  memmap_describe ( start, 1, &region );
91  DBGC_MEMMAP ( segment, &region );
92 
93  /* Fail unless region is usable and sufficiently large */
94  if ( ( ! memmap_is_usable ( &region ) ) || ( region.max < max ) ) {
95  DBGC ( segment, "SEGMENT [%#08lx,%#08lx,%#08lx) does not fit "
96  "into available memory\n", start, mid, end );
97  return -ERANGE_SEGMENT;
98  }
99 
100  /* Found valid region: zero bss and return */
101  memset ( ( segment + filesz ), 0, ( memsz - filesz ) );
102  return 0;
103 }
static int memmap_is_usable(const struct memmap_region *region)
Check if memory region is usable.
Definition: memmap.h:86
#define EINVAL
Invalid argument.
Definition: errno.h:428
uint16_t segment
Code segment.
Definition: librm.h:138
Error message tables.
#define max(x, y)
Definition: ath.h:40
uint64_t max
Maximum address in region.
Definition: memmap.h:52
Error codes.
uint16_t mid
Middle 16 bits of address.
Definition: librm.h:144
#define __einfo_errortab(einfo)
Definition: errortab.h:23
#define DBGC(...)
Definition: compiler.h:505
#define DBGC_MEMMAP(...)
Definition: memmap.h:206
uint32_t start
Starting offset.
Definition: netvsc.h:12
Executable image segments.
void memmap_describe(uint64_t min, int hide, struct memmap_region *region)
Describe memory region from system memory map.
Definition: null_memmap.h:28
Access to external ("user") memory.
#define ERANGE_SEGMENT
Segment-specific error messages.
Definition: segment.c:46
#define EINFO_ERANGE_SEGMENT
Definition: segment.c:47
unsigned long physaddr_t
Definition: stdint.h:20
uint32_t end
Ending offset.
Definition: netvsc.h:18
static size_t memsz
Definition: fdtmem.c:51
int prep_segment(void *segment, size_t filesz, size_t memsz)
Prepare segment for loading.
Definition: segment.c:61
struct errortab segment_errors [] __errortab
Definition: segment.c:49
A memory region descriptor.
Definition: memmap.h:48
System memory map.
String functions.
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
void * memset(void *dest, int character, size_t len) __nonnull