Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/libofw/ofw_copy.c
34677 views
1
/*-
2
* Copyright (c) 1998 Michael Smith <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
/*
28
* MD primitives supporting placement of module data
29
*
30
* XXX should check load address/size against memory top.
31
*/
32
#include <stand.h>
33
34
#include "libofw.h"
35
36
#define READIN_BUF (4 * 1024)
37
#define PAGE_SIZE 0x1000
38
#define PAGE_MASK 0x0fff
39
#define MAPMEM_PAGE_INC 128 /* Half-MB at a time */
40
41
42
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
43
44
static int
45
ofw_mapmem(vm_offset_t dest, const size_t len)
46
{
47
void *destp, *addr;
48
size_t dlen;
49
size_t resid;
50
size_t nlen;
51
static vm_offset_t last_dest = 0;
52
static size_t last_len = 0;
53
54
nlen = len;
55
/*
56
* Check to see if this region fits in a prior mapping.
57
* Allocations are generally sequential, so only check
58
* the last one.
59
*/
60
if (dest >= last_dest &&
61
(dest + len) <= (last_dest + last_len)) {
62
return (0);
63
}
64
65
/*
66
* Trim area covered by existing mapping, if any
67
*/
68
if (dest < (last_dest + last_len) && dest >= last_dest) {
69
nlen -= (last_dest + last_len) - dest;
70
dest = last_dest + last_len;
71
}
72
73
destp = (void *)(dest & ~PAGE_MASK);
74
resid = dest & PAGE_MASK;
75
76
/*
77
* To avoid repeated mappings on small allocations,
78
* never map anything less than MAPMEM_PAGE_INC pages at a time
79
*/
80
if ((nlen + resid) < PAGE_SIZE*MAPMEM_PAGE_INC) {
81
dlen = PAGE_SIZE*MAPMEM_PAGE_INC;
82
} else
83
dlen = roundup(nlen + resid, PAGE_SIZE);
84
85
if (OF_call_method("claim", memory, 3, 1, destp, dlen, 0, &addr)
86
== -1) {
87
printf("ofw_mapmem: physical claim failed\n");
88
return (ENOMEM);
89
}
90
91
/*
92
* We only do virtual memory management when real_mode is false.
93
*/
94
if (real_mode == 0) {
95
if (OF_call_method("claim", mmu, 3, 1, destp, dlen, 0, &addr)
96
== -1) {
97
printf("ofw_mapmem: virtual claim failed\n");
98
return (ENOMEM);
99
}
100
101
if (OF_call_method("map", mmu, 4, 0, destp, destp, dlen, 0)
102
== -1) {
103
printf("ofw_mapmem: map failed\n");
104
return (ENOMEM);
105
}
106
}
107
last_dest = (vm_offset_t) destp;
108
last_len = dlen;
109
110
return (0);
111
}
112
113
ssize_t
114
ofw_copyin(const void *src, vm_offset_t dest, const size_t len)
115
{
116
if (ofw_mapmem(dest, len)) {
117
printf("ofw_copyin: map error\n");
118
return (0);
119
}
120
121
bcopy(src, (void *)dest, len);
122
return (len);
123
}
124
125
ssize_t
126
ofw_copyout(const vm_offset_t src, void *dest, const size_t len)
127
{
128
bcopy((void *)src, dest, len);
129
return (len);
130
}
131
132
ssize_t
133
ofw_readin(readin_handle_t fd, vm_offset_t dest, const size_t len)
134
{
135
void *buf;
136
size_t resid, chunk, get;
137
ssize_t got;
138
vm_offset_t p;
139
140
p = dest;
141
142
chunk = min(READIN_BUF, len);
143
buf = malloc(chunk);
144
if (buf == NULL) {
145
printf("ofw_readin: buf malloc failed\n");
146
return (0);
147
}
148
149
if (ofw_mapmem(dest, len)) {
150
printf("ofw_readin: map error\n");
151
free(buf);
152
return (0);
153
}
154
155
for (resid = len; resid > 0; resid -= got, p += got) {
156
get = min(chunk, resid);
157
got = VECTX_READ(fd, buf, get);
158
159
if (got <= 0) {
160
if (got < 0)
161
printf("ofw_readin: read failed\n");
162
break;
163
}
164
165
bcopy(buf, (void *)p, got);
166
}
167
168
free(buf);
169
return (len - resid);
170
}
171
172