MFC
This commit is contained in:
commit
d7073a2b3b
@ -50,12 +50,4 @@ troffrc!X100 troffrc!X100-12 troffrc!lj4 troff!lbp troffrc!html
|
||||
.\" Handle paper formats
|
||||
.do mso papersize.tmac
|
||||
.
|
||||
.\" Disable SGR support in grotty(1).
|
||||
.if n \{\
|
||||
. do nop \X'tty: sgr 0'
|
||||
. sp -1
|
||||
. nr nl 0-1
|
||||
. nr % -1
|
||||
.\}
|
||||
.
|
||||
.\" Don't let blank lines creep in here.
|
||||
|
@ -1281,6 +1281,7 @@ pcap_cleanup_bpf(pcap_t *p)
|
||||
munmap(p->md.zbuf1, p->md.zbufsize);
|
||||
if (p->md.zbuf2 != MAP_FAILED && p->md.zbuf2 != NULL)
|
||||
munmap(p->md.zbuf2, p->md.zbufsize);
|
||||
p->buffer = NULL;
|
||||
}
|
||||
#endif
|
||||
if (p->md.device != NULL) {
|
||||
|
@ -306,7 +306,7 @@ gpart_autofill_resize(struct gctl_req *req)
|
||||
struct ggeom *gp;
|
||||
struct gprovider *pp;
|
||||
off_t last, size, start, new_size;
|
||||
off_t lba, new_lba, alignment;
|
||||
off_t lba, new_lba, alignment, offset;
|
||||
const char *s;
|
||||
int error, idx;
|
||||
|
||||
@ -341,6 +341,9 @@ gpart_autofill_resize(struct gctl_req *req)
|
||||
errc(EXIT_FAILURE, error, "Invalid alignment param");
|
||||
if (alignment == 0)
|
||||
errx(EXIT_FAILURE, "Invalid alignment param");
|
||||
lba = pp->lg_stripesize / pp->lg_sectorsize;
|
||||
if (lba > 0)
|
||||
alignment = g_lcm(lba, alignment);
|
||||
}
|
||||
error = gctl_delete_param(req, "alignment");
|
||||
if (error)
|
||||
@ -356,12 +359,10 @@ gpart_autofill_resize(struct gctl_req *req)
|
||||
/* no autofill necessary. */
|
||||
if (alignment == 1)
|
||||
goto done;
|
||||
if (new_size > alignment)
|
||||
new_size = ALIGNDOWN(new_size, alignment);
|
||||
}
|
||||
|
||||
offset = pp->lg_stripeoffset / pp->lg_sectorsize;
|
||||
last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0);
|
||||
last = ALIGNDOWN(last, alignment);
|
||||
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
|
||||
s = find_provcfg(pp, "index");
|
||||
if (s == NULL)
|
||||
@ -375,24 +376,32 @@ gpart_autofill_resize(struct gctl_req *req)
|
||||
s = find_provcfg(pp, "start");
|
||||
start = (off_t)strtoimax(s, NULL, 0);
|
||||
s = find_provcfg(pp, "end");
|
||||
lba = (off_t)strtoimax(s, NULL, 0) + 1;
|
||||
lba = (off_t)strtoimax(s, NULL, 0);
|
||||
size = lba - start + 1;
|
||||
|
||||
if (lba > last) {
|
||||
geom_deletetree(&mesh);
|
||||
return (ENOSPC);
|
||||
if (new_size > 0 && new_size <= size) {
|
||||
/* The start offset may be not aligned, so we align the end
|
||||
* offset and then calculate the size.
|
||||
*/
|
||||
new_size = ALIGNDOWN(start + offset + new_size,
|
||||
alignment) - start - offset;
|
||||
goto done;
|
||||
}
|
||||
size = lba - start;
|
||||
pp = find_provider(gp, lba);
|
||||
if (pp == NULL)
|
||||
new_size = ALIGNDOWN(last - start + 1, alignment);
|
||||
else {
|
||||
|
||||
pp = find_provider(gp, lba + 1);
|
||||
if (pp == NULL) {
|
||||
new_size = ALIGNDOWN(last + offset + 1, alignment) -
|
||||
start - offset;
|
||||
if (new_size < size)
|
||||
return (ENOSPC);
|
||||
} else {
|
||||
s = find_provcfg(pp, "start");
|
||||
new_lba = (off_t)strtoimax(s, NULL, 0);
|
||||
/*
|
||||
* Is there any free space between current and
|
||||
* next providers?
|
||||
*/
|
||||
new_lba = ALIGNUP(new_lba, alignment);
|
||||
new_lba = ALIGNDOWN(new_lba + offset, alignment) - offset;
|
||||
if (new_lba > lba)
|
||||
new_size = new_lba - start;
|
||||
else {
|
||||
@ -482,10 +491,16 @@ gpart_autofill(struct gctl_req *req)
|
||||
if (has_size && has_start && !has_alignment)
|
||||
goto done;
|
||||
|
||||
/* Adjust parameters to offset value for better alignment */
|
||||
s = find_provcfg(pp, "offset");
|
||||
offset = (s == NULL) ? 0:
|
||||
(off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
|
||||
/*
|
||||
* If stripesize is not zero, then recalculate alignment value.
|
||||
* Use LCM from stripesize and user specified alignment.
|
||||
*/
|
||||
len = pp->lg_stripesize / pp->lg_sectorsize;
|
||||
if (len > 0 )
|
||||
alignment = g_lcm(len, alignment);
|
||||
|
||||
/* Adjust parameters to stripeoffset */
|
||||
offset = pp->lg_stripeoffset / pp->lg_sectorsize;
|
||||
start = ALIGNUP(start + offset, alignment);
|
||||
if (size + offset > alignment)
|
||||
size = ALIGNDOWN(size + offset, alignment);
|
||||
|
@ -61,7 +61,8 @@ which is used to define a logical partition.
|
||||
The
|
||||
.Dv GEOM_PART_EBR_COMPAT
|
||||
option enables backward compatibility for partition names
|
||||
in the EBR scheme. Also it makes impossible any types of actions
|
||||
in the EBR scheme.
|
||||
Also it makes impossible any types of actions
|
||||
with such partitions.
|
||||
The
|
||||
.Dv GEOM_PART_GPT
|
||||
@ -170,7 +171,7 @@ utility:
|
||||
.\" ==== SHOW ====
|
||||
.Nm
|
||||
.Cm show
|
||||
.Op Fl l | Fl r
|
||||
.Op Fl l | r
|
||||
.Op Fl p
|
||||
.Op Ar geom ...
|
||||
.\" ==== UNDO ====
|
||||
@ -200,11 +201,14 @@ The partition begins on the logical block address given by the
|
||||
option.
|
||||
Its size is given by the
|
||||
.Fl s Ar size
|
||||
option. SI unit suffixes are allowed. One or both
|
||||
option.
|
||||
SI unit suffixes are allowed.
|
||||
One or both
|
||||
.Fl b
|
||||
and
|
||||
.Fl s
|
||||
options can be omitted. If so they are automatically calculated.
|
||||
options can be omitted.
|
||||
If so they are automatically calculated.
|
||||
The type of the partition is given by the
|
||||
.Fl t Ar type
|
||||
option.
|
||||
@ -399,7 +403,7 @@ about its use.
|
||||
Recover corrupt partition's scheme metadata on the geom
|
||||
.Ar geom .
|
||||
See the section entitled
|
||||
.Sx "RECOVERING"
|
||||
.Sx RECOVERING
|
||||
below for the additional information.
|
||||
.Pp
|
||||
Additional options include:
|
||||
@ -453,7 +457,7 @@ action and given from standard input.
|
||||
Only partition table may be restored.
|
||||
This action does not affect content of partitions.
|
||||
This mean that you should copy your data from backup after restoring
|
||||
partition table and write bootcode again if it is needed.
|
||||
partition table and write bootcode again if it is needed.
|
||||
.Pp
|
||||
Additional options include:
|
||||
.Bl -tag -width 10n
|
||||
@ -474,7 +478,7 @@ about its use.
|
||||
.It Cm set
|
||||
Set the named attribute on the partition entry.
|
||||
See the section entitled
|
||||
.Sx "ATTRIBUTES"
|
||||
.Sx ATTRIBUTES
|
||||
below for a list of available attributes.
|
||||
.Pp
|
||||
Additional options include:
|
||||
@ -511,7 +515,7 @@ action and can be used to undo any changes that have not been committed.
|
||||
.It Cm unset
|
||||
Clear the named attribute on the partition entry.
|
||||
See the section entitled
|
||||
.Sx "ATTRIBUTES"
|
||||
.Sx ATTRIBUTES
|
||||
below for a list of available attributes.
|
||||
.Pp
|
||||
Additional options include:
|
||||
@ -616,75 +620,75 @@ by GPT.
|
||||
.El
|
||||
.Sh ATTRIBUTES
|
||||
The scheme-specific attributes for EBR:
|
||||
.Bl -tag -width ".Ar active"
|
||||
.It Ar active
|
||||
.Bl -tag -width ".Cm active"
|
||||
.It Cm active
|
||||
.El
|
||||
.Pp
|
||||
The scheme-specific attributes for GPT:
|
||||
.Bl -tag -width ".Ar bootfailed"
|
||||
.It Ar bootme
|
||||
.Bl -tag -width ".Cm bootfailed"
|
||||
.It Cm bootme
|
||||
When set, the
|
||||
.Nm gptboot
|
||||
stage 1 boot loader will try to boot the system from this partition.
|
||||
Multiple partitions might be marked with the
|
||||
.Ar bootme
|
||||
.Cm bootme
|
||||
attribute.
|
||||
In such scenario the
|
||||
.Nm gptboot
|
||||
will try all
|
||||
.Ar bootme
|
||||
.Cm bootme
|
||||
partitions one by one, until the next boot stage is successfully entered.
|
||||
.It Ar bootonce
|
||||
.It Cm bootonce
|
||||
Setting this attribute automatically sets the
|
||||
.Ar bootme
|
||||
.Cm bootme
|
||||
attribute.
|
||||
When set, the
|
||||
.Nm gptboot
|
||||
stage 1 boot loader will try to boot the system from this partition only once.
|
||||
Partitions with both
|
||||
.Ar bootonce
|
||||
.Cm bootonce
|
||||
and
|
||||
.Ar bootme
|
||||
.Cm bootme
|
||||
attributes are tried before partitions with only the
|
||||
.Ar bootme
|
||||
.Cm bootme
|
||||
attribute.
|
||||
Before
|
||||
.Ar bootonce
|
||||
.Cm bootonce
|
||||
partition is tried, the
|
||||
.Nm gptboot
|
||||
removes the
|
||||
.Ar bootme
|
||||
.Cm bootme
|
||||
attribute and tries to execute the next boot stage.
|
||||
If it fails, the
|
||||
.Ar bootonce
|
||||
.Cm bootonce
|
||||
attribute that is now alone is replaced with the
|
||||
.Ar bootfailed
|
||||
.Cm bootfailed
|
||||
attribute.
|
||||
If the execution of the next boot stage succeeds, but the system is not fully
|
||||
booted, the
|
||||
.Nm gptboot
|
||||
will look for
|
||||
.Ar bootonce
|
||||
.Cm bootonce
|
||||
attributes alone (without the
|
||||
.Ar bootme
|
||||
.Cm bootme
|
||||
attribute) on the next system boot and will replace those with the
|
||||
.Ar bootfailed
|
||||
.Cm bootfailed
|
||||
attribute.
|
||||
If the system is fully booted, the
|
||||
.Pa /etc/rc.d/gptboot
|
||||
start-up script will look for partition with the
|
||||
.Ar bootonce
|
||||
.Cm bootonce
|
||||
attribute alone, will remove the attribute and log that the system was
|
||||
successfully booted from this partition.
|
||||
There should be at most one
|
||||
.Ar bootonce
|
||||
.Cm bootonce
|
||||
partition when system is successfully booted.
|
||||
Multiple partitions might be marked with the
|
||||
.Ar bootonce
|
||||
.Cm bootonce
|
||||
and
|
||||
.Ar bootme
|
||||
.Cm bootme
|
||||
attribute pairs.
|
||||
.It Ar bootfailed
|
||||
.It Cm bootfailed
|
||||
This attribute should not be manually managed.
|
||||
It is managed by the
|
||||
.Nm gptboot
|
||||
@ -692,24 +696,24 @@ stage 1 boot loader and the
|
||||
.Pa /etc/rc.d/gptboot
|
||||
start-up script.
|
||||
This attribute is used to mark partitions that had the
|
||||
.Ar bootonce
|
||||
.Cm bootonce
|
||||
attribute set, but we failed to boot from them.
|
||||
Once we successfully boot, the
|
||||
.Pa /etc/rc.d/gptboot
|
||||
script will log all the partitions we failed to boot from and will remove the
|
||||
.Ar bootfailed
|
||||
.Cm bootfailed
|
||||
attributes.
|
||||
.El
|
||||
.Pp
|
||||
The scheme-specific attributes for MBR:
|
||||
.Bl -tag -width ".Ar active"
|
||||
.It Ar active
|
||||
.Bl -tag -width ".Cm active"
|
||||
.It Cm active
|
||||
.El
|
||||
.Pp
|
||||
The scheme-specific attributes for PC98:
|
||||
.Bl -tag -width ".Ar bootable"
|
||||
.It Ar active
|
||||
.It Ar bootable
|
||||
.Bl -tag -width ".Cm bootable"
|
||||
.It Cm active
|
||||
.It Cm bootable
|
||||
.El
|
||||
.Sh OPERATIONAL FLAGS
|
||||
Actions other than the
|
||||
@ -747,7 +751,7 @@ reports about corruption.
|
||||
Any changes in corrupt table are prohibited except
|
||||
.Cm destroy
|
||||
and
|
||||
.Cm recover .
|
||||
.Cm recover .
|
||||
.Pp
|
||||
In case when only first sector is corrupt kernel can not detect GPT even
|
||||
if partition table is not corrupt.
|
||||
@ -771,16 +775,15 @@ GEOM: provider: the secondary GPT table is corrupt or invalid.
|
||||
GEOM: provider: using the primary only -- recovery suggested.
|
||||
.Ed
|
||||
.Pp
|
||||
Also
|
||||
.Cm gpart
|
||||
commands like
|
||||
.Cm show ,
|
||||
.Cm status
|
||||
Also
|
||||
.Nm
|
||||
commands like
|
||||
.Cm show , status
|
||||
and
|
||||
.Cm list
|
||||
will report about corrupt table.
|
||||
.Pp
|
||||
In case when the size of device has changed (e.g. volume expansion) the
|
||||
In case when the size of device has changed (e.g.\& volume expansion) the
|
||||
secondary GPT header will become located not in the last sector.
|
||||
This is not a metadata corruption, but it is dangerous because any
|
||||
corruption of the primary GPT will lead to lost of partition table.
|
||||
@ -789,19 +792,19 @@ Kernel reports about this problem with message:
|
||||
GEOM: provider: the secondary GPT header is not in the last LBA.
|
||||
.Ed
|
||||
.Pp
|
||||
A corrupt table can be recovered with
|
||||
.Cm gpart recover
|
||||
A corrupt table can be recovered with
|
||||
.Cm recover
|
||||
command.
|
||||
This command does reconstruction of corrupt metadata using
|
||||
This command does reconstruction of corrupt metadata using
|
||||
known valid metadata.
|
||||
Also it can relocate secondary GPT to the end of device.
|
||||
.Pp
|
||||
.Pa NOTE :
|
||||
The GEOM class PART can detect the same partition table on different GEOM
|
||||
.Em NOTE :
|
||||
The GEOM class PART can detect the same partition table on different GEOM
|
||||
providers and some of them will be marked as corrupt.
|
||||
Be careful when choosing a provider for recovering.
|
||||
If you choose incorrectly you can destroy the metadata of another GEOM class,
|
||||
e.g. GEOM MIRROR or GEOM LABEL.
|
||||
e.g.\& GEOM MIRROR or GEOM LABEL.
|
||||
.Sh SYSCTL VARIABLES
|
||||
The following
|
||||
.Xr sysctl 8
|
||||
@ -815,20 +818,21 @@ This variable controls the behaviour of metadata integrity checks.
|
||||
When integrity checks are enabled
|
||||
.Nm PART
|
||||
GEOM class verifies all generic partition parameters that it gets from the
|
||||
disk metadata. If some inconsistency is detected, partition table will be
|
||||
disk metadata.
|
||||
If some inconsistency is detected, partition table will be
|
||||
rejected with a diagnostic message:
|
||||
.Pa GEOM_PART: Integrity check failed (provider, scheme) .
|
||||
.Sy "GEOM_PART: Integrity check failed (provider, scheme)" .
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
Exit status is 0 on success, and 1 if the command fails.
|
||||
.Sh EXAMPLES
|
||||
Create GPT scheme on
|
||||
.Pa ad0 .
|
||||
.Pa ad0 :
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart create -s GPT ad0
|
||||
.Ed
|
||||
.Pp
|
||||
Embed GPT bootstrap code into protective MBR.
|
||||
Embed GPT bootstrap code into protective MBR:
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart bootcode -b /boot/pmbr ad0
|
||||
.Ed
|
||||
@ -854,15 +858,19 @@ future need (e.g.\& from a ZFS partition).
|
||||
.Pp
|
||||
Create a 512MB-sized
|
||||
.Cm freebsd-ufs
|
||||
partition that would contain UFS where the system boots from.
|
||||
partition that would contain UFS where the system boots from:
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart add -b 162 -s 1048576 -t freebsd-ufs ad0
|
||||
.Ed
|
||||
.Pp
|
||||
Create MBR scheme on
|
||||
.Pa ada0 ,
|
||||
then create 30GB-sized FreeBSD slice, mark it active and
|
||||
install boot0 boot manager:
|
||||
then create 30GB-sized
|
||||
.Fx
|
||||
slice, mark it active and
|
||||
install
|
||||
.Nm boot0
|
||||
boot manager:
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart create -s MBR ada0
|
||||
/sbin/gpart add -t freebsd -s 30G ada0
|
||||
@ -870,7 +878,11 @@ install boot0 boot manager:
|
||||
/sbin/gpart bootcode -b /boot/boot0 ada0
|
||||
.Ed
|
||||
.Pp
|
||||
Now create BSD scheme (BSD label) with ability to have up to 20 partitions:
|
||||
Now create
|
||||
.Bx
|
||||
scheme
|
||||
.Pf ( Bx
|
||||
label) with ability to have up to 20 partitions:
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart create -s BSD -n 20 ada0s1
|
||||
.Ed
|
||||
@ -881,20 +893,22 @@ Create 1GB-sized UFS partition and 4GB-sized swap partition:
|
||||
/sbin/gpart add -t freebsd-swap -s 4G ada0s1
|
||||
.Ed
|
||||
.Pp
|
||||
Install bootstrap code for the BSD label:
|
||||
Install bootstrap code for the
|
||||
.Bx
|
||||
label:
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart bootcode -b /boot/boot ada0s1
|
||||
.Ed
|
||||
.Pp
|
||||
Create VTOC8 scheme on
|
||||
.Pa da0 .
|
||||
.Pa da0 :
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart create -s VTOC8 da0
|
||||
.Ed
|
||||
.Pp
|
||||
Create a 512MB-sized
|
||||
.Cm freebsd-ufs
|
||||
partition that would contain UFS where the system boots from.
|
||||
partition that would contain UFS where the system boots from:
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart add -s 512M -t freebsd-ufs da0
|
||||
.Ed
|
||||
@ -906,29 +920,29 @@ partition that would contain UFS and aligned on 4KB boundaries:
|
||||
/sbin/gpart add -s 15G -t freebsd-ufs -a 4k da0
|
||||
.Ed
|
||||
.Pp
|
||||
After having created all required partitions, embed bootstrap code into them.
|
||||
After having created all required partitions, embed bootstrap code into them:
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart bootcode -p /boot/boot1 da0
|
||||
.Ed
|
||||
.Pp
|
||||
Create backup of partition table from
|
||||
.Pa da0
|
||||
.Pa da0 :
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart backup da0 > da0.backup
|
||||
.Ed
|
||||
.Pp
|
||||
Restore partition table from backup to
|
||||
.Pa da0
|
||||
.Pa da0 :
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart restore -l da0 < /mnt/da0.backup
|
||||
.Ed
|
||||
.Pp
|
||||
Clone partition table from
|
||||
.Pa ada0
|
||||
to
|
||||
.Pa ada1
|
||||
and
|
||||
.Pa ada2
|
||||
Clone partition table from
|
||||
.Pa ada0
|
||||
to
|
||||
.Pa ada1
|
||||
and
|
||||
.Pa ada2 :
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart backup ada0 | /sbin/gpart restore -F ada1 ada2
|
||||
.Ed
|
||||
|
@ -54,10 +54,10 @@ INDXBIB?= indxbib
|
||||
PIC?= pic
|
||||
REFER?= refer
|
||||
.for _dev in ${PRINTERDEVICE:Mascii}
|
||||
ROFF.ascii?= groff -Tascii ${TRFLAGS} -mtty-char ${MACROS} -o${PAGES}
|
||||
ROFF.ascii?= groff -Tascii -P-c ${TRFLAGS} -mtty-char ${MACROS} ${PAGES:C/^/-o/1}
|
||||
.endfor
|
||||
.for _dev in ${PRINTERDEVICE:Nascii}
|
||||
ROFF.${_dev}?= groff -T${_dev} ${TRFLAGS} ${MACROS} -o${PAGES}
|
||||
ROFF.${_dev}?= groff -T${_dev} ${TRFLAGS} ${MACROS} ${PAGES:C/^/-o/1}
|
||||
.endfor
|
||||
SOELIM?= soelim
|
||||
TBL?= tbl
|
||||
@ -94,8 +94,6 @@ DFILE.${_dev}= ${DOC}.${_dev}${DCOMPRESS_EXT}
|
||||
.endif
|
||||
.endfor
|
||||
|
||||
PAGES?= 1-
|
||||
|
||||
UNROFF?= unroff
|
||||
HTML_SPLIT?= yes
|
||||
UNROFFFLAGS?= -fhtml
|
||||
|
@ -114,11 +114,12 @@ struct disk_params {
|
||||
u_int64_t sectors; /* Total number sectors */
|
||||
};
|
||||
|
||||
#define TRIM_MAX_BLOCKS 4
|
||||
#define TRIM_MAX_RANGES TRIM_MAX_BLOCKS * 64
|
||||
#define TRIM_MAX_BLOCKS 8
|
||||
#define TRIM_MAX_RANGES (TRIM_MAX_BLOCKS * 64)
|
||||
#define TRIM_MAX_BIOS (TRIM_MAX_RANGES * 4)
|
||||
struct trim_request {
|
||||
uint8_t data[TRIM_MAX_RANGES * 8];
|
||||
struct bio *bps[TRIM_MAX_RANGES];
|
||||
struct bio *bps[TRIM_MAX_BIOS];
|
||||
};
|
||||
|
||||
struct ada_softc {
|
||||
@ -1067,7 +1068,8 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
(bp = bioq_first(&softc->trim_queue)) != 0) {
|
||||
struct trim_request *req = &softc->trim_req;
|
||||
struct bio *bp1;
|
||||
int bps = 0, ranges = 0;
|
||||
uint64_t lastlba = (uint64_t)-1;
|
||||
int bps = 0, c, lastcount = 0, off, ranges = 0;
|
||||
|
||||
softc->trim_running = 1;
|
||||
bzero(req, sizeof(*req));
|
||||
@ -1078,10 +1080,22 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
softc->params.secsize;
|
||||
|
||||
bioq_remove(&softc->trim_queue, bp1);
|
||||
while (count > 0) {
|
||||
int c = min(count, 0xffff);
|
||||
int off = ranges * 8;
|
||||
|
||||
/* Try to extend the previous range. */
|
||||
if (lba == lastlba) {
|
||||
c = min(count, 0xffff - lastcount);
|
||||
lastcount += c;
|
||||
off = (ranges - 1) * 8;
|
||||
req->data[off + 6] = lastcount & 0xff;
|
||||
req->data[off + 7] =
|
||||
(lastcount >> 8) & 0xff;
|
||||
count -= c;
|
||||
lba += c;
|
||||
}
|
||||
|
||||
while (count > 0) {
|
||||
c = min(count, 0xffff);
|
||||
off = ranges * 8;
|
||||
req->data[off + 0] = lba & 0xff;
|
||||
req->data[off + 1] = (lba >> 8) & 0xff;
|
||||
req->data[off + 2] = (lba >> 16) & 0xff;
|
||||
@ -1092,11 +1106,14 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
req->data[off + 7] = (c >> 8) & 0xff;
|
||||
lba += c;
|
||||
count -= c;
|
||||
lastcount = c;
|
||||
ranges++;
|
||||
}
|
||||
lastlba = lba;
|
||||
req->bps[bps++] = bp1;
|
||||
bp1 = bioq_first(&softc->trim_queue);
|
||||
if (bp1 == NULL ||
|
||||
if (bps >= TRIM_MAX_BIOS ||
|
||||
bp1 == NULL ||
|
||||
bp1->bio_bcount / softc->params.secsize >
|
||||
(softc->trim_max_ranges - ranges) * 0xffff)
|
||||
break;
|
||||
@ -1370,8 +1387,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
(struct trim_request *)ataio->data_ptr;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < softc->trim_max_ranges &&
|
||||
req->bps[i]; i++) {
|
||||
for (i = 1; i < TRIM_MAX_BIOS && req->bps[i]; i++) {
|
||||
struct bio *bp1 = req->bps[i];
|
||||
|
||||
bp1->bio_resid = bp->bio_resid;
|
||||
|
@ -87,7 +87,6 @@ powerpc/aim/moea64_if.m optional aim
|
||||
powerpc/aim/moea64_native.c optional aim
|
||||
powerpc/aim/mp_cpudep.c optional aim smp
|
||||
powerpc/aim/nexus.c optional aim
|
||||
powerpc/aim/ofwmagic.S optional aim
|
||||
powerpc/aim/slb.c optional aim powerpc64
|
||||
powerpc/aim/swtch32.S optional aim powerpc
|
||||
powerpc/aim/swtch64.S optional aim powerpc64
|
||||
@ -137,6 +136,10 @@ powerpc/ofw/ofw_pcibus.c optional pci aim
|
||||
powerpc/ofw/ofw_pcib_pci.c optional pci aim
|
||||
powerpc/ofw/ofw_real.c optional aim
|
||||
powerpc/ofw/ofw_syscons.c optional sc aim
|
||||
powerpc/ofw/ofwcall32.S optional aim powerpc
|
||||
powerpc/ofw/ofwcall64.S optional aim powerpc64
|
||||
powerpc/ofw/ofwmagic.S optional aim
|
||||
powerpc/ofw/rtas.c optional aim
|
||||
powerpc/powermac/ata_kauai.c optional powermac ata | powermac atamacio
|
||||
powerpc/powermac/ata_macio.c optional powermac ata | powermac atamacio
|
||||
powerpc/powermac/ata_dbdma.c optional powermac ata | powermac atamacio
|
||||
|
@ -735,6 +735,16 @@ typedef struct {
|
||||
#define HAL_PHYERR_PARAM_ENABLE 0x8000 /* Enable/Disable if applicable */
|
||||
|
||||
|
||||
/*
|
||||
* Flag for setting QUIET period
|
||||
*/
|
||||
typedef enum {
|
||||
HAL_QUIET_DISABLE = 0x0,
|
||||
HAL_QUIET_ENABLE = 0x1,
|
||||
HAL_QUIET_ADD_CURRENT_TSF = 0x2, /* add current TSF to next_start offset */
|
||||
HAL_QUIET_ADD_SWBA_RESP_TIME = 0x4, /* add beacon response time to next_start offset */
|
||||
} HAL_QUIET_FLAG;
|
||||
|
||||
/*
|
||||
* Hardware Access Layer (HAL) API.
|
||||
*
|
||||
@ -909,6 +919,9 @@ struct ath_hal {
|
||||
u_int __ahdecl(*ah_getCTSTimeout)(struct ath_hal*);
|
||||
HAL_BOOL __ahdecl(*ah_setDecompMask)(struct ath_hal*, uint16_t, int);
|
||||
void __ahdecl(*ah_setCoverageClass)(struct ath_hal*, uint8_t, int);
|
||||
HAL_STATUS __ahdecl(*ah_setQuiet)(struct ath_hal *ah, uint32_t period,
|
||||
uint32_t duration, uint32_t nextStart,
|
||||
HAL_QUIET_FLAG flag);
|
||||
|
||||
/* DFS functions */
|
||||
void __ahdecl(*ah_enableDfs)(struct ath_hal *ah,
|
||||
|
@ -506,6 +506,8 @@ extern HAL_BOOL ar5212SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE,
|
||||
extern HAL_BOOL ar5212GetDiagState(struct ath_hal *ah, int request,
|
||||
const void *args, uint32_t argsize,
|
||||
void **result, uint32_t *resultsize);
|
||||
extern HAL_STATUS ar5212SetQuiet(struct ath_hal *ah, uint32_t period,
|
||||
uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag);
|
||||
|
||||
extern HAL_BOOL ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode,
|
||||
int setChip);
|
||||
|
@ -127,6 +127,7 @@ static const struct ath_hal_private ar5212hal = {{
|
||||
.ah_getCTSTimeout = ar5212GetCTSTimeout,
|
||||
.ah_setDecompMask = ar5212SetDecompMask,
|
||||
.ah_setCoverageClass = ar5212SetCoverageClass,
|
||||
.ah_setQuiet = ar5212SetQuiet,
|
||||
|
||||
/* DFS Functions */
|
||||
.ah_enableDfs = ar5212EnableDfs,
|
||||
|
@ -634,6 +634,20 @@ ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
|
||||
}
|
||||
}
|
||||
|
||||
HAL_STATUS
|
||||
ar5212SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
|
||||
uint32_t nextStart, HAL_QUIET_FLAG flag)
|
||||
{
|
||||
OS_REG_WRITE(ah, AR_QUIET2, period | (duration << AR_QUIET2_QUIET_DUR_S));
|
||||
if (flag & HAL_QUIET_ENABLE) {
|
||||
OS_REG_WRITE(ah, AR_QUIET1, nextStart | (1 << 16));
|
||||
}
|
||||
else {
|
||||
OS_REG_WRITE(ah, AR_QUIET1, nextStart);
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ar5212SetPCUConfig(struct ath_hal *ah)
|
||||
{
|
||||
|
@ -300,6 +300,7 @@
|
||||
#define AR_QUIET1_NEXT_QUIET 0xffff
|
||||
#define AR_QUIET1_QUIET_ENABLE 0x10000 /* Enable Quiet time operation */
|
||||
#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x20000 /* Do we ack/cts during quiet period */
|
||||
#define AR_QUIET1_QUIET_ACK_CTS_ENABLE_S 17
|
||||
|
||||
#define AR_QUIET2 0x8100 /* More Quiet time programming */
|
||||
#define AR_QUIET2_QUIET_PER_S 0 /* Periodicity of quiet period (TU) */
|
||||
|
@ -194,6 +194,8 @@ extern uint32_t ar5416Get11nExtBusy(struct ath_hal *ah);
|
||||
extern void ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode);
|
||||
extern HAL_HT_RXCLEAR ar5416Get11nRxClear(struct ath_hal *ah);
|
||||
extern void ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear);
|
||||
extern HAL_STATUS ar5416SetQuiet(struct ath_hal *ah, uint32_t period,
|
||||
uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag);
|
||||
extern HAL_STATUS ar5416GetCapability(struct ath_hal *ah,
|
||||
HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result);
|
||||
extern HAL_BOOL ar5416GetDiagState(struct ath_hal *ah, int request,
|
||||
|
@ -139,6 +139,7 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc,
|
||||
ah->ah_setAntennaSwitch = ar5416SetAntennaSwitch;
|
||||
ah->ah_setDecompMask = ar5416SetDecompMask;
|
||||
ah->ah_setCoverageClass = ar5416SetCoverageClass;
|
||||
ah->ah_setQuiet = ar5416SetQuiet;
|
||||
|
||||
ah->ah_resetKeyCacheEntry = ar5416ResetKeyCacheEntry;
|
||||
ah->ah_setKeyCacheEntry = ar5416SetKeyCacheEntry;
|
||||
|
@ -273,6 +273,35 @@ ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear)
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX shouldn't be here! */
|
||||
#define TU_TO_USEC(_tu) ((_tu) << 10)
|
||||
|
||||
HAL_STATUS
|
||||
ar5416SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
|
||||
uint32_t nextStart, HAL_QUIET_FLAG flag)
|
||||
{
|
||||
uint32_t period_us = TU_TO_USEC(period); /* convert to us unit */
|
||||
uint32_t nextStart_us = TU_TO_USEC(nextStart); /* convert to us unit */
|
||||
if (flag & HAL_QUIET_ENABLE) {
|
||||
if ((!nextStart) || (flag & HAL_QUIET_ADD_CURRENT_TSF)) {
|
||||
/* Add the nextStart offset to the current TSF */
|
||||
nextStart_us += OS_REG_READ(ah, AR_TSF_L32);
|
||||
}
|
||||
if (flag & HAL_QUIET_ADD_SWBA_RESP_TIME) {
|
||||
nextStart_us += ath_hal_sw_beacon_response_time;
|
||||
}
|
||||
OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
|
||||
OS_REG_WRITE(ah, AR_QUIET2, SM(duration, AR_QUIET2_QUIET_DUR));
|
||||
OS_REG_WRITE(ah, AR_QUIET_PERIOD, period_us);
|
||||
OS_REG_WRITE(ah, AR_NEXT_QUIET, nextStart_us);
|
||||
OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
|
||||
} else {
|
||||
OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
#undef TU_TO_USEC
|
||||
|
||||
HAL_STATUS
|
||||
ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
|
||||
uint32_t capability, uint32_t *result)
|
||||
|
@ -154,6 +154,12 @@ g_disk_access(struct g_provider *pp, int r, int w, int e)
|
||||
}
|
||||
pp->mediasize = dp->d_mediasize;
|
||||
pp->sectorsize = dp->d_sectorsize;
|
||||
if (dp->d_flags & DISKFLAG_CANDELETE)
|
||||
pp->flags |= G_PF_CANDELETE;
|
||||
else
|
||||
pp->flags &= ~G_PF_CANDELETE;
|
||||
pp->stripeoffset = dp->d_stripeoffset;
|
||||
pp->stripesize = dp->d_stripesize;
|
||||
dp->d_flags |= DISKFLAG_OPEN;
|
||||
if (dp->d_maxsize == 0) {
|
||||
printf("WARNING: Disk drive %s%d has no d_maxsize\n",
|
||||
|
@ -248,6 +248,7 @@ g_part_check_integrity(struct g_part_table *table, struct g_consumer *cp)
|
||||
{
|
||||
struct g_part_entry *e1, *e2;
|
||||
struct g_provider *pp;
|
||||
off_t offset;
|
||||
int failed;
|
||||
|
||||
failed = 0;
|
||||
@ -294,6 +295,16 @@ g_part_check_integrity(struct g_part_table *table, struct g_consumer *cp)
|
||||
(intmax_t)table->gpt_last);
|
||||
failed++;
|
||||
}
|
||||
if (pp->stripesize > 0) {
|
||||
offset = e1->gpe_start * pp->sectorsize;
|
||||
if (e1->gpe_offset > offset)
|
||||
offset = e1->gpe_offset;
|
||||
if ((offset + pp->stripeoffset) % pp->stripesize) {
|
||||
DPRINTF("partition %d is not aligned on %u "
|
||||
"bytes\n", e1->gpe_index, pp->stripesize);
|
||||
/* Don't treat this as a critical failure */
|
||||
}
|
||||
}
|
||||
e2 = e1;
|
||||
while ((e2 = LIST_NEXT(e2, gpe_entry)) != NULL) {
|
||||
if (e2->gpe_deleted || e2->gpe_internal)
|
||||
@ -723,7 +734,11 @@ g_part_ctl_add(struct gctl_req *req, struct g_part_parms *gpp)
|
||||
if (gpp->gpp_parms & G_PART_PARM_OUTPUT) {
|
||||
sb = sbuf_new_auto();
|
||||
G_PART_FULLNAME(table, entry, sb, gp->name);
|
||||
sbuf_cat(sb, " added\n");
|
||||
if (pp->stripesize > 0 && entry->gpe_pp->stripeoffset != 0)
|
||||
sbuf_printf(sb, " added, but partition is not "
|
||||
"aligned on %u bytes\n", pp->stripesize);
|
||||
else
|
||||
sbuf_cat(sb, " added\n");
|
||||
sbuf_finish(sb);
|
||||
gctl_set_param(req, "output", sbuf_data(sb), sbuf_len(sb) + 1);
|
||||
sbuf_delete(sb);
|
||||
|
@ -126,7 +126,7 @@ static void tunclone(void *arg, struct ucred *cred, char *name,
|
||||
int namelen, struct cdev **dev);
|
||||
static void tuncreate(const char *name, struct cdev *dev);
|
||||
static int tunifioctl(struct ifnet *, u_long, caddr_t);
|
||||
static int tuninit(struct ifnet *);
|
||||
static void tuninit(struct ifnet *);
|
||||
static int tunmodevent(module_t, int, void *);
|
||||
static int tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
struct route *ro);
|
||||
@ -494,14 +494,13 @@ tunclose(struct cdev *dev, int foo, int bar, struct thread *td)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
tuninit(struct ifnet *ifp)
|
||||
{
|
||||
struct tun_softc *tp = ifp->if_softc;
|
||||
#ifdef INET
|
||||
struct ifaddr *ifa;
|
||||
#endif
|
||||
int error = 0;
|
||||
|
||||
TUNDEBUG(ifp, "tuninit\n");
|
||||
|
||||
@ -528,7 +527,6 @@ tuninit(struct ifnet *ifp)
|
||||
if_addr_runlock(ifp);
|
||||
#endif
|
||||
mtx_unlock(&tp->tun_mtx);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -552,12 +550,12 @@ tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
mtx_unlock(&tp->tun_mtx);
|
||||
break;
|
||||
case SIOCSIFADDR:
|
||||
error = tuninit(ifp);
|
||||
TUNDEBUG(ifp, "address set, error=%d\n", error);
|
||||
tuninit(ifp);
|
||||
TUNDEBUG(ifp, "address set\n");
|
||||
break;
|
||||
case SIOCSIFDSTADDR:
|
||||
error = tuninit(ifp);
|
||||
TUNDEBUG(ifp, "destination address set, error=%d\n", error);
|
||||
tuninit(ifp);
|
||||
TUNDEBUG(ifp, "destination address set\n");
|
||||
break;
|
||||
case SIOCSIFMTU:
|
||||
ifp->if_mtu = ifr->ifr_mtu;
|
||||
@ -857,7 +855,6 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
|
||||
struct tun_softc *tp = dev->si_drv1;
|
||||
struct ifnet *ifp = TUN2IFP(tp);
|
||||
struct mbuf *m;
|
||||
int error = 0;
|
||||
uint32_t family;
|
||||
int isr;
|
||||
|
||||
@ -877,7 +874,7 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
|
||||
|
||||
if ((m = m_uiotombuf(uio, M_DONTWAIT, 0, 0, M_PKTHDR)) == NULL) {
|
||||
ifp->if_ierrors++;
|
||||
return (error);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
|
@ -100,10 +100,8 @@ powerpc_interrupt(struct trapframe *framep)
|
||||
default:
|
||||
/* Re-enable interrupts if applicable. */
|
||||
ee = framep->srr1 & PSL_EE;
|
||||
if (ee != 0) {
|
||||
if (ee != 0)
|
||||
mtmsr(mfmsr() | ee);
|
||||
isync();
|
||||
}
|
||||
trap(framep);
|
||||
}
|
||||
}
|
||||
|
@ -87,9 +87,6 @@ GLOBAL(tmpstk)
|
||||
GLOBAL(esym)
|
||||
.long 0 /* end of symbol table */
|
||||
|
||||
GLOBAL(ofmsr)
|
||||
.long 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
|
||||
|
||||
#define INTRCNT_COUNT 256 /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
|
||||
GLOBAL(intrnames)
|
||||
.space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
|
||||
@ -99,16 +96,6 @@ GLOBAL(intrcnt)
|
||||
.space INTRCNT_COUNT * 4 * 2
|
||||
GLOBAL(eintrcnt)
|
||||
|
||||
/*
|
||||
* File-scope for locore.S
|
||||
*/
|
||||
idle_u:
|
||||
.long 0 /* fake uarea during idle after exit */
|
||||
openfirmware_entry:
|
||||
.long 0 /* Open Firmware entry point */
|
||||
srsave:
|
||||
.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
|
||||
.text
|
||||
.globl btext
|
||||
btext:
|
||||
|
@ -75,8 +75,7 @@
|
||||
.globl kernbase
|
||||
.set kernbase, KERNBASE
|
||||
|
||||
#define TMPSTKSZ 8192 /* 8K temporary stack */
|
||||
#define OFWSTKSZ 4096 /* 4K Open Firmware stack */
|
||||
#define TMPSTKSZ 16384 /* 16K temporary stack */
|
||||
|
||||
/*
|
||||
* Globals
|
||||
@ -85,14 +84,9 @@
|
||||
.align 4
|
||||
GLOBAL(tmpstk)
|
||||
.space TMPSTKSZ
|
||||
GLOBAL(ofwstk)
|
||||
.space OFWSTKSZ
|
||||
GLOBAL(esym)
|
||||
.llong 0 /* end of symbol table */
|
||||
|
||||
GLOBAL(ofmsr)
|
||||
.llong 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
|
||||
|
||||
#define INTRCNT_COUNT 256 /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
|
||||
GLOBAL(intrnames)
|
||||
.space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
|
||||
@ -102,16 +96,6 @@ GLOBAL(intrcnt)
|
||||
.space INTRCNT_COUNT * 4 * 2
|
||||
GLOBAL(eintrcnt)
|
||||
|
||||
/*
|
||||
* File-scope for locore.S
|
||||
*/
|
||||
idle_u:
|
||||
.llong 0 /* fake uarea during idle after exit */
|
||||
openfirmware_entry:
|
||||
.llong 0 /* Open Firmware entry point */
|
||||
srsave:
|
||||
.llong 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
|
||||
.text
|
||||
.globl btext
|
||||
btext:
|
||||
@ -207,122 +191,6 @@ ASENTRY(__start)
|
||||
tocbase:
|
||||
.llong .TOC.@tocbase
|
||||
|
||||
/*
|
||||
* Open Firmware Real-mode Entry Point. This is a huge pain.
|
||||
*/
|
||||
|
||||
ASENTRY(ofw_32bit_mode_entry)
|
||||
mflr %r0
|
||||
std %r0,16(%r1)
|
||||
stdu %r1,-208(%r1)
|
||||
|
||||
/*
|
||||
* We need to save the following, because OF's register save/
|
||||
* restore code assumes that the contents of registers are
|
||||
* at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
|
||||
* get placed in that order in the stack.
|
||||
*/
|
||||
|
||||
mfcr %r4
|
||||
std %r4,48(%r1)
|
||||
std %r13,56(%r1)
|
||||
std %r14,64(%r1)
|
||||
std %r15,72(%r1)
|
||||
std %r16,80(%r1)
|
||||
std %r17,88(%r1)
|
||||
std %r18,96(%r1)
|
||||
std %r19,104(%r1)
|
||||
std %r20,112(%r1)
|
||||
std %r21,120(%r1)
|
||||
std %r22,128(%r1)
|
||||
std %r23,136(%r1)
|
||||
std %r24,144(%r1)
|
||||
std %r25,152(%r1)
|
||||
std %r26,160(%r1)
|
||||
std %r27,168(%r1)
|
||||
std %r28,176(%r1)
|
||||
std %r29,184(%r1)
|
||||
std %r30,192(%r1)
|
||||
std %r31,200(%r1)
|
||||
|
||||
/* Record the old MSR */
|
||||
mfmsr %r6
|
||||
|
||||
/* read client interface handler */
|
||||
lis %r4,openfirmware_entry@ha
|
||||
ld %r4,openfirmware_entry@l(%r4)
|
||||
|
||||
/*
|
||||
* Set the MSR to the OF value. This has the side effect of disabling
|
||||
* exceptions, which is important for the next few steps.
|
||||
*/
|
||||
|
||||
lis %r5,ofmsr@ha
|
||||
ld %r5,ofmsr@l(%r5)
|
||||
mtmsrd %r5
|
||||
isync
|
||||
|
||||
/*
|
||||
* Set up OF stack. This needs to be accessible in real mode and
|
||||
* use the 32-bit ABI stack frame format. The pointer to the current
|
||||
* kernel stack is placed at the very top of the stack along with
|
||||
* the old MSR so we can get them back later.
|
||||
*/
|
||||
mr %r5,%r1
|
||||
lis %r1,(ofwstk+OFWSTKSZ-32)@ha
|
||||
addi %r1,%r1,(ofwstk+OFWSTKSZ-32)@l
|
||||
std %r5,8(%r1) /* Save real stack pointer */
|
||||
std %r2,16(%r1) /* Save old TOC */
|
||||
std %r6,24(%r1) /* Save old MSR */
|
||||
li %r5,0
|
||||
stw %r5,4(%r1)
|
||||
stw %r5,0(%r1)
|
||||
|
||||
/* Finally, branch to OF */
|
||||
mtctr %r4
|
||||
bctrl
|
||||
|
||||
/* Reload stack pointer and MSR from the OFW stack */
|
||||
ld %r6,24(%r1)
|
||||
ld %r2,16(%r1)
|
||||
ld %r1,8(%r1)
|
||||
|
||||
/* Now set the real MSR */
|
||||
mtmsrd %r6
|
||||
isync
|
||||
|
||||
/* Sign-extend the return value from OF */
|
||||
extsw %r3,%r3
|
||||
|
||||
/* Restore all the non-volatile registers */
|
||||
ld %r5,48(%r1)
|
||||
mtcr %r5
|
||||
ld %r13,56(%r1)
|
||||
ld %r14,64(%r1)
|
||||
ld %r15,72(%r1)
|
||||
ld %r16,80(%r1)
|
||||
ld %r17,88(%r1)
|
||||
ld %r18,96(%r1)
|
||||
ld %r19,104(%r1)
|
||||
ld %r20,112(%r1)
|
||||
ld %r21,120(%r1)
|
||||
ld %r22,128(%r1)
|
||||
ld %r23,136(%r1)
|
||||
ld %r24,144(%r1)
|
||||
ld %r25,152(%r1)
|
||||
ld %r26,160(%r1)
|
||||
ld %r27,168(%r1)
|
||||
ld %r28,176(%r1)
|
||||
ld %r29,184(%r1)
|
||||
ld %r30,192(%r1)
|
||||
ld %r31,200(%r1)
|
||||
|
||||
/* Restore the stack and link register */
|
||||
ld %r1,0(%r1)
|
||||
ld %r0,16(%r1)
|
||||
mtlr %r0
|
||||
blr
|
||||
|
||||
/*
|
||||
* int setfault()
|
||||
*
|
||||
|
@ -132,6 +132,7 @@ extern vm_offset_t ksym_start, ksym_end;
|
||||
|
||||
int cold = 1;
|
||||
#ifdef __powerpc64__
|
||||
extern int n_slbs;
|
||||
int cacheline_size = 128;
|
||||
#else
|
||||
int cacheline_size = 32;
|
||||
@ -251,7 +252,6 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
|
||||
vm_offset_t basekernel, void *mdp)
|
||||
{
|
||||
struct pcpu *pc;
|
||||
vm_offset_t end;
|
||||
void *generictrap;
|
||||
size_t trap_offset;
|
||||
void *kmdp;
|
||||
@ -263,7 +263,6 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
|
||||
int ppc64;
|
||||
#endif
|
||||
|
||||
end = 0;
|
||||
kmdp = NULL;
|
||||
trap_offset = 0;
|
||||
cacheline_warn = 0;
|
||||
@ -279,7 +278,8 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
|
||||
if (kmdp != NULL) {
|
||||
boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
|
||||
kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
|
||||
end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
|
||||
endkernel = ulmax(endkernel, MD_FETCH(kmdp,
|
||||
MODINFOMD_KERNEND, vm_offset_t));
|
||||
#ifdef DDB
|
||||
ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
|
||||
ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
|
||||
@ -338,13 +338,13 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
|
||||
|
||||
kdb_init();
|
||||
|
||||
/*
|
||||
* PowerPC 970 CPUs have a misfeature requested by Apple that makes
|
||||
* them pretend they have a 32-byte cacheline. Turn this off
|
||||
* before we measure the cacheline size.
|
||||
*/
|
||||
|
||||
/* Various very early CPU fix ups */
|
||||
switch (mfpvr() >> 16) {
|
||||
/*
|
||||
* PowerPC 970 CPUs have a misfeature requested by Apple that
|
||||
* makes them pretend they have a 32-byte cacheline. Turn this
|
||||
* off before we measure the cacheline size.
|
||||
*/
|
||||
case IBM970:
|
||||
case IBM970FX:
|
||||
case IBM970MP:
|
||||
@ -353,6 +353,12 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
|
||||
scratch &= ~HID5_970_DCBZ_SIZE_HI;
|
||||
mtspr(SPR_HID5, scratch);
|
||||
break;
|
||||
#ifdef __powerpc64__
|
||||
case IBMPOWER7:
|
||||
/* XXX: get from ibm,slb-size in device tree */
|
||||
n_slbs = 32;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -368,7 +374,6 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
|
||||
|
||||
msr = mfmsr();
|
||||
mtmsr((msr & ~(PSL_IR | PSL_DR)) | PSL_RI);
|
||||
isync();
|
||||
|
||||
/*
|
||||
* Measure the cacheline size using dcbz
|
||||
@ -503,7 +508,6 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
|
||||
* Restore MSR
|
||||
*/
|
||||
mtmsr(msr);
|
||||
isync();
|
||||
|
||||
/* Warn if cachline size was not determined */
|
||||
if (cacheline_warn == 1) {
|
||||
@ -527,8 +531,7 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
|
||||
pmap_mmu_install(MMU_TYPE_OEA, BUS_PROBE_GENERIC);
|
||||
|
||||
pmap_bootstrap(startkernel, endkernel);
|
||||
mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI);
|
||||
isync();
|
||||
mtmsr(PSL_KERNSET & ~PSL_EE);
|
||||
|
||||
/*
|
||||
* Initialize params/tunables that are derived from memsize
|
||||
|
@ -587,25 +587,8 @@ moea_pte_change(struct pte *pt, struct pte *pvo_pt, vm_offset_t va)
|
||||
/*
|
||||
* Quick sort callout for comparing memory regions.
|
||||
*/
|
||||
static int mr_cmp(const void *a, const void *b);
|
||||
static int om_cmp(const void *a, const void *b);
|
||||
|
||||
static int
|
||||
mr_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct mem_region *regiona;
|
||||
const struct mem_region *regionb;
|
||||
|
||||
regiona = a;
|
||||
regionb = b;
|
||||
if (regiona->mr_start < regionb->mr_start)
|
||||
return (-1);
|
||||
else if (regiona->mr_start > regionb->mr_start)
|
||||
return (1);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
om_cmp(const void *a, const void *b)
|
||||
{
|
||||
@ -723,7 +706,6 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
|
||||
mem_regions(&pregions, &pregions_sz, ®ions, ®ions_sz);
|
||||
CTR0(KTR_PMAP, "moea_bootstrap: physical memory");
|
||||
|
||||
qsort(pregions, pregions_sz, sizeof(*pregions), mr_cmp);
|
||||
for (i = 0; i < pregions_sz; i++) {
|
||||
vm_offset_t pa;
|
||||
vm_offset_t end;
|
||||
@ -752,7 +734,7 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
|
||||
|
||||
if (sizeof(phys_avail)/sizeof(phys_avail[0]) < regions_sz)
|
||||
panic("moea_bootstrap: phys_avail too small");
|
||||
qsort(regions, regions_sz, sizeof(*regions), mr_cmp);
|
||||
|
||||
phys_avail_count = 0;
|
||||
physsz = 0;
|
||||
hwphyssz = 0;
|
||||
|
@ -165,8 +165,8 @@ __FBSDID("$FreeBSD$");
|
||||
void moea64_release_vsid(uint64_t vsid);
|
||||
uintptr_t moea64_get_unique_vsid(void);
|
||||
|
||||
#define DISABLE_TRANS(msr) msr = mfmsr(); mtmsr(msr & ~PSL_DR); isync()
|
||||
#define ENABLE_TRANS(msr) mtmsr(msr); isync()
|
||||
#define DISABLE_TRANS(msr) msr = mfmsr(); mtmsr(msr & ~PSL_DR)
|
||||
#define ENABLE_TRANS(msr) mtmsr(msr)
|
||||
|
||||
#define VSID_MAKE(sr, hash) ((sr) | (((hash) & 0xfffff) << 4))
|
||||
#define VSID_TO_HASH(vsid) (((vsid) >> 4) & 0xfffff)
|
||||
@ -476,25 +476,8 @@ moea64_calc_wimg(vm_offset_t pa, vm_memattr_t ma)
|
||||
/*
|
||||
* Quick sort callout for comparing memory regions.
|
||||
*/
|
||||
static int mr_cmp(const void *a, const void *b);
|
||||
static int om_cmp(const void *a, const void *b);
|
||||
|
||||
static int
|
||||
mr_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct mem_region *regiona;
|
||||
const struct mem_region *regionb;
|
||||
|
||||
regiona = a;
|
||||
regionb = b;
|
||||
if (regiona->mr_start < regionb->mr_start)
|
||||
return (-1);
|
||||
else if (regiona->mr_start > regionb->mr_start)
|
||||
return (1);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
om_cmp(const void *a, const void *b)
|
||||
{
|
||||
@ -710,10 +693,9 @@ moea64_early_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelen
|
||||
mem_regions(&pregions, &pregions_sz, ®ions, ®ions_sz);
|
||||
CTR0(KTR_PMAP, "moea64_bootstrap: physical memory");
|
||||
|
||||
qsort(pregions, pregions_sz, sizeof(*pregions), mr_cmp);
|
||||
if (sizeof(phys_avail)/sizeof(phys_avail[0]) < regions_sz)
|
||||
panic("moea64_bootstrap: phys_avail too small");
|
||||
qsort(regions, regions_sz, sizeof(*regions), mr_cmp);
|
||||
|
||||
phys_avail_count = 0;
|
||||
physsz = 0;
|
||||
hwphyssz = 0;
|
||||
@ -898,7 +880,7 @@ moea64_late_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend
|
||||
* Initialize MMU and remap early physical mappings
|
||||
*/
|
||||
MMU_CPU_BOOTSTRAP(mmup,0);
|
||||
mtmsr(mfmsr() | PSL_DR | PSL_IR); isync();
|
||||
mtmsr(mfmsr() | PSL_DR | PSL_IR);
|
||||
pmap_bootstrapped++;
|
||||
bs_remap_earlyboot();
|
||||
|
||||
|
@ -185,8 +185,8 @@ TLBIE(uint64_t vpn) {
|
||||
mtx_unlock_spin(&tlbie_mutex);
|
||||
}
|
||||
|
||||
#define DISABLE_TRANS(msr) msr = mfmsr(); mtmsr(msr & ~PSL_DR); isync()
|
||||
#define ENABLE_TRANS(msr) mtmsr(msr); isync()
|
||||
#define DISABLE_TRANS(msr) msr = mfmsr(); mtmsr(msr & ~PSL_DR)
|
||||
#define ENABLE_TRANS(msr) mtmsr(msr)
|
||||
|
||||
/*
|
||||
* PTEG data.
|
||||
@ -344,7 +344,7 @@ moea64_cpu_bootstrap_native(mmu_t mmup, int ap)
|
||||
* Initialize segment registers and MMU
|
||||
*/
|
||||
|
||||
mtmsr(mfmsr() & ~PSL_DR & ~PSL_IR); isync();
|
||||
mtmsr(mfmsr() & ~PSL_DR & ~PSL_IR);
|
||||
|
||||
/*
|
||||
* Install kernel SLB entries
|
||||
|
@ -87,7 +87,6 @@ cpudep_ap_bootstrap(void)
|
||||
|
||||
msr = PSL_KERNSET & ~PSL_EE;
|
||||
mtmsr(msr);
|
||||
isync();
|
||||
|
||||
pcpup->pc_curthread = pcpup->pc_idlethread;
|
||||
pcpup->pc_curpcb = pcpup->pc_curthread->td_pcb;
|
||||
@ -344,6 +343,10 @@ cpudep_ap_setup()
|
||||
|
||||
break;
|
||||
default:
|
||||
#ifdef __powerpc64__
|
||||
if (!(mfmsr() & PSL_HV)) /* Rely on HV to have set things up */
|
||||
break;
|
||||
#endif
|
||||
printf("WARNING: Unknown CPU type. Cache performace may be "
|
||||
"suboptimal.\n");
|
||||
break;
|
||||
|
@ -51,8 +51,9 @@ uintptr_t moea64_get_unique_vsid(void);
|
||||
void moea64_release_vsid(uint64_t vsid);
|
||||
static void slb_zone_init(void *);
|
||||
|
||||
uma_zone_t slbt_zone;
|
||||
uma_zone_t slb_cache_zone;
|
||||
static uma_zone_t slbt_zone;
|
||||
static uma_zone_t slb_cache_zone;
|
||||
int n_slbs = 64;
|
||||
|
||||
SYSINIT(slb_zone_init, SI_SUB_KMEM, SI_ORDER_ANY, slb_zone_init, NULL);
|
||||
|
||||
@ -426,16 +427,18 @@ slb_insert_kernel(uint64_t slbe, uint64_t slbv)
|
||||
|
||||
/* Check for an unused slot, abusing the user slot as a full flag */
|
||||
if (slbcache[USER_SLB_SLOT].slbe == 0) {
|
||||
for (i = 0; i < USER_SLB_SLOT; i++) {
|
||||
for (i = 0; i < n_slbs; i++) {
|
||||
if (i == USER_SLB_SLOT)
|
||||
continue;
|
||||
if (!(slbcache[i].slbe & SLBE_VALID))
|
||||
goto fillkernslb;
|
||||
}
|
||||
|
||||
if (i == USER_SLB_SLOT)
|
||||
if (i == n_slbs)
|
||||
slbcache[USER_SLB_SLOT].slbe = 1;
|
||||
}
|
||||
|
||||
for (i = mftb() % 64, j = 0; j < 64; j++, i = (i+1) % 64) {
|
||||
for (i = mftb() % n_slbs, j = 0; j < n_slbs; j++, i = (i+1) % n_slbs) {
|
||||
if (i == USER_SLB_SLOT)
|
||||
continue;
|
||||
|
||||
@ -443,9 +446,11 @@ slb_insert_kernel(uint64_t slbe, uint64_t slbv)
|
||||
break;
|
||||
}
|
||||
|
||||
KASSERT(j < 64, ("All kernel SLB slots locked!"));
|
||||
KASSERT(j < n_slbs, ("All kernel SLB slots locked!"));
|
||||
|
||||
fillkernslb:
|
||||
KASSERT(i != USER_SLB_SLOT,
|
||||
("Filling user SLB slot with a kernel mapping"));
|
||||
slbcache[i].slbv = slbv;
|
||||
slbcache[i].slbe = slbe | (uint64_t)i;
|
||||
|
||||
@ -466,11 +471,11 @@ slb_insert_user(pmap_t pm, struct slb *slb)
|
||||
|
||||
PMAP_LOCK_ASSERT(pm, MA_OWNED);
|
||||
|
||||
if (pm->pm_slb_len < 64) {
|
||||
if (pm->pm_slb_len < n_slbs) {
|
||||
i = pm->pm_slb_len;
|
||||
pm->pm_slb_len++;
|
||||
} else {
|
||||
i = mftb() % 64;
|
||||
i = mftb() % n_slbs;
|
||||
}
|
||||
|
||||
/* Note that this replacement is atomic with respect to trap_subr */
|
||||
@ -521,8 +526,9 @@ slb_zone_init(void *dummy)
|
||||
|
||||
slbt_zone = uma_zcreate("SLB tree node", sizeof(struct slbtnode),
|
||||
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
|
||||
slb_cache_zone = uma_zcreate("SLB cache", 64*sizeof(struct slb *),
|
||||
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
|
||||
slb_cache_zone = uma_zcreate("SLB cache",
|
||||
(n_slbs + 1)*sizeof(struct slb *), NULL, NULL, NULL, NULL,
|
||||
UMA_ALIGN_PTR, UMA_ZONE_VM);
|
||||
|
||||
if (platform_real_maxaddr() != VM_MAX_ADDRESS) {
|
||||
uma_zone_set_allocf(slb_cache_zone, slb_uma_real_alloc);
|
||||
|
@ -53,55 +53,53 @@
|
||||
* User SRs are loaded through a pointer to the current pmap.
|
||||
*/
|
||||
restore_usersrs:
|
||||
GET_CPUINFO(%r28);
|
||||
ld %r28,PC_USERSLB(%r28);
|
||||
GET_CPUINFO(%r28)
|
||||
ld %r28,PC_USERSLB(%r28)
|
||||
li %r29, 0 /* Set the counter to zero */
|
||||
|
||||
slbia
|
||||
slbmfee %r31,%r29
|
||||
clrrdi %r31,%r31,28
|
||||
slbie %r31
|
||||
instuserslb:
|
||||
ld %r31, 0(%r28); /* Load SLB entry pointer */
|
||||
cmpli 0, %r31, 0; /* If NULL, stop */
|
||||
beqlr;
|
||||
1: ld %r31, 0(%r28) /* Load SLB entry pointer */
|
||||
cmpli 0, %r31, 0 /* If NULL, stop */
|
||||
beqlr
|
||||
|
||||
ld %r30, 0(%r31) /* Load SLBV */
|
||||
ld %r31, 8(%r31) /* Load SLBE */
|
||||
or %r31, %r31, %r29 /* Set SLBE slot */
|
||||
slbmte %r30, %r31; /* Install SLB entry */
|
||||
slbmte %r30, %r31 /* Install SLB entry */
|
||||
|
||||
addi %r28, %r28, 8; /* Advance pointer */
|
||||
addi %r29, %r29, 1;
|
||||
cmpli 0, %r29, 64; /* Repeat if we are not at the end */
|
||||
blt instuserslb;
|
||||
blr;
|
||||
addi %r28, %r28, 8 /* Advance pointer */
|
||||
addi %r29, %r29, 1
|
||||
b 1b /* Repeat */
|
||||
|
||||
/*
|
||||
* Kernel SRs are loaded directly from the PCPU fields
|
||||
*/
|
||||
restore_kernsrs:
|
||||
GET_CPUINFO(%r28);
|
||||
addi %r28,%r28,PC_KERNSLB;
|
||||
GET_CPUINFO(%r28)
|
||||
addi %r28,%r28,PC_KERNSLB
|
||||
li %r29, 0 /* Set the counter to zero */
|
||||
|
||||
slbia
|
||||
slbmfee %r31,%r29
|
||||
clrrdi %r31,%r31,28
|
||||
slbie %r31
|
||||
instkernslb:
|
||||
ld %r31, 8(%r28); /* Load SLBE */
|
||||
1: cmpli 0, %r29, USER_SLB_SLOT /* Skip the user slot */
|
||||
beq- 2f
|
||||
|
||||
cmpli 0, %r31, 0; /* If SLBE is not valid, stop */
|
||||
beqlr;
|
||||
ld %r31, 8(%r28) /* Load SLBE */
|
||||
cmpli 0, %r31, 0 /* If SLBE is not valid, stop */
|
||||
beqlr
|
||||
ld %r30, 0(%r28) /* Load SLBV */
|
||||
slbmte %r30, %r31; /* Install SLB entry */
|
||||
slbmte %r30, %r31 /* Install SLB entry */
|
||||
|
||||
addi %r28, %r28, 16; /* Advance pointer */
|
||||
addi %r29, %r29, 1;
|
||||
cmpli 0, %r29, USER_SLB_SLOT; /* Repeat if we are not at the end */
|
||||
blt instkernslb;
|
||||
blr;
|
||||
2: addi %r28, %r28, 16 /* Advance pointer */
|
||||
addi %r29, %r29, 1
|
||||
cmpli 0, %r29, 64 /* Repeat if we are not at the end */
|
||||
blt 1b
|
||||
blr
|
||||
|
||||
/*
|
||||
* FRAME_SETUP assumes:
|
||||
|
61
sys/powerpc/include/rtas.h
Normal file
61
sys/powerpc/include/rtas.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*-
|
||||
* Copyright (c) 2011 Nathan Whitehorn
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_RTAS_H_
|
||||
#define _MACHINE_RTAS_H_
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
/*
|
||||
* RTAS functions are defined by 32-bit integer tokens. These vary from
|
||||
* system to system, and can be looked up from their standardized names
|
||||
* using rtas_token_lookup(). If RTAS is not available, rtas_token_lookup()
|
||||
* and rtas_call_method() return -1; this can be checked in advance using
|
||||
* rtas_exists(). Otherwise, rtas_call_method() returns one of the RTAS
|
||||
* status codes from the bottom of this file.
|
||||
*/
|
||||
|
||||
int rtas_exists(void);
|
||||
int rtas_call_method(cell_t token, int nargs, int nreturns, ...);
|
||||
cell_t rtas_token_lookup(const char *method);
|
||||
|
||||
/* RTAS Status Codes: see CHRP or PAPR specification */
|
||||
#define RTAS_OK 0
|
||||
#define RTAS_HW_ERROR -1
|
||||
#define RTAS_BUSY -2
|
||||
#define RTAS_PARAM_ERROR -3
|
||||
#define RTAS_STATE_CHANGE -7
|
||||
#define RTAS_VENDOR_BEGIN 9000
|
||||
#define RTAS_EXTENDED_DELAY 9900
|
||||
#define RTAS_ISOLATION_ERROR -9000
|
||||
#define RTAS_VENDOR_ERROR_BEGIN -9004
|
||||
|
||||
#endif /* _MACHINE_RTAS_H_ */
|
||||
|
@ -65,7 +65,7 @@
|
||||
/*
|
||||
* User segment for copyin/out
|
||||
*/
|
||||
#define USER_SLB_SLOT 63
|
||||
#define USER_SLB_SLOT 0
|
||||
#define USER_SLB_SLBE (((USER_ADDR >> ADDR_SR_SHFT) << SLBE_ESID_SHIFT) | \
|
||||
SLBE_VALID | USER_SLB_SLOT)
|
||||
|
||||
|
@ -66,7 +66,8 @@ static struct mem_region OFfree[OFMEM_REGIONS + 3];
|
||||
static int nOFmem;
|
||||
|
||||
extern register_t ofmsr[5];
|
||||
static int (*ofwcall)(void *);
|
||||
int ofwcall(void *);
|
||||
extern void *openfirmware_entry;
|
||||
static void *fdt;
|
||||
int ofw_real_mode;
|
||||
|
||||
@ -318,19 +319,6 @@ OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *))
|
||||
else
|
||||
ofw_real_mode = 1;
|
||||
|
||||
ofwcall = NULL;
|
||||
|
||||
#ifdef __powerpc64__
|
||||
/*
|
||||
* For PPC64, we need to use some hand-written
|
||||
* asm trampolines to get to OF.
|
||||
*/
|
||||
if (openfirm != NULL)
|
||||
ofwcall = ofw_32bit_mode_entry;
|
||||
#else
|
||||
ofwcall = openfirm;
|
||||
#endif
|
||||
|
||||
fdt = fdt_ptr;
|
||||
|
||||
#ifdef FDT_DTB_STATIC
|
||||
@ -345,7 +333,7 @@ OF_bootstrap()
|
||||
{
|
||||
boolean_t status = FALSE;
|
||||
|
||||
if (ofwcall != NULL) {
|
||||
if (openfirmware_entry != NULL) {
|
||||
if (ofw_real_mode) {
|
||||
status = OF_install(OFW_STD_REAL, 0);
|
||||
} else {
|
||||
|
@ -205,13 +205,14 @@ ofw_real_bounce_alloc(void *junk)
|
||||
|
||||
/*
|
||||
* Allocate a page of contiguous, wired physical memory that can
|
||||
* fit into a 32-bit address space.
|
||||
* fit into a 32-bit address space and accessed from real mode.
|
||||
*/
|
||||
|
||||
mtx_lock(&of_bounce_mtx);
|
||||
|
||||
of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0,
|
||||
0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE);
|
||||
of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0, 0,
|
||||
ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
|
||||
PAGE_SIZE);
|
||||
|
||||
of_bounce_phys = vtophys(of_bounce_virt);
|
||||
of_bounce_size = PAGE_SIZE;
|
||||
|
154
sys/powerpc/ofw/ofwcall32.S
Normal file
154
sys/powerpc/ofw/ofwcall32.S
Normal file
@ -0,0 +1,154 @@
|
||||
/*-
|
||||
* Copyright (C) 2009-2011 Nathan Whitehorn
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <machine/trap.h>
|
||||
#include <machine/param.h>
|
||||
#include <machine/spr.h>
|
||||
#include <machine/asm.h>
|
||||
|
||||
#define OFWSTKSZ 4096 /* 4K Open Firmware stack */
|
||||
|
||||
/*
|
||||
* Globals
|
||||
*/
|
||||
.data
|
||||
GLOBAL(ofmsr)
|
||||
.long 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
|
||||
GLOBAL(rtasmsr)
|
||||
.long 0
|
||||
GLOBAL(openfirmware_entry)
|
||||
.long 0 /* Open Firmware entry point */
|
||||
GLOBAL(rtas_entry)
|
||||
.long 0 /* RTAS entry point */
|
||||
|
||||
.align 4
|
||||
ofwstk:
|
||||
.space OFWSTKSZ
|
||||
rtas_regsave:
|
||||
.space 4
|
||||
|
||||
/*
|
||||
* Open Firmware Entry Point. May need to enter real mode.
|
||||
*
|
||||
* C prototype: int ofwcall(void *callbuffer);
|
||||
*/
|
||||
|
||||
ASENTRY(ofwcall)
|
||||
mflr %r0
|
||||
stw %r0,4(%r1)
|
||||
|
||||
/* Record the old MSR */
|
||||
mfmsr %r6
|
||||
|
||||
/* read client interface handler */
|
||||
lis %r4,openfirmware_entry@ha
|
||||
lwz %r4,openfirmware_entry@l(%r4)
|
||||
|
||||
/*
|
||||
* Set the MSR to the OF value. This has the side effect of disabling
|
||||
* exceptions, which prevents preemption later.
|
||||
*/
|
||||
|
||||
lis %r5,ofmsr@ha
|
||||
lwz %r5,ofmsr@l(%r5)
|
||||
mtmsr %r5
|
||||
isync
|
||||
|
||||
/*
|
||||
* Set up OF stack. This needs to be potentially accessible in real mode
|
||||
* The pointer to the current kernel stack is placed at the very
|
||||
* top of the stack along with the old MSR so we can get them back
|
||||
* later.
|
||||
*/
|
||||
mr %r5,%r1
|
||||
lis %r1,(ofwstk+OFWSTKSZ-16)@ha
|
||||
addi %r1,%r1,(ofwstk+OFWSTKSZ-16)@l
|
||||
stw %r5,8(%r1) /* Save real stack pointer */
|
||||
stw %r6,12(%r1) /* Save old MSR */
|
||||
li %r5,0
|
||||
stw %r5,4(%r1)
|
||||
stw %r5,0(%r1)
|
||||
|
||||
/* Finally, branch to OF */
|
||||
mtctr %r4
|
||||
bctrl
|
||||
|
||||
/* Reload stack pointer and MSR from the OFW stack */
|
||||
lwz %r6,12(%r1)
|
||||
lwz %r1,8(%r1)
|
||||
|
||||
/* Now set the real MSR */
|
||||
mtmsr %r6
|
||||
isync
|
||||
|
||||
/* Return */
|
||||
lwz %r0,4(%r1)
|
||||
mtlr %r0
|
||||
blr
|
||||
|
||||
/*
|
||||
* RTAS Entry Point. Similar to the OF one, but simpler (no separate stack)
|
||||
*
|
||||
* C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
|
||||
*/
|
||||
|
||||
ASENTRY(rtascall)
|
||||
mflr %r0
|
||||
stw %r0,4(%r1)
|
||||
|
||||
/* Record the old MSR to real-mode-accessible area */
|
||||
mfmsr %r0
|
||||
lis %r5,rtas_regsave@ha
|
||||
stw %r0,rtas_regsave@l(%r5)
|
||||
|
||||
/* read client interface handler */
|
||||
lis %r5,rtas_entry@ha
|
||||
lwz %r5,rtas_entry@l(%r5)
|
||||
|
||||
/* Set the MSR to the RTAS value */
|
||||
lis %r6,rtasmsr@ha
|
||||
lwz %r6,rtasmsr@l(%r6)
|
||||
mtmsr %r6
|
||||
isync
|
||||
|
||||
/* Branch to RTAS */
|
||||
mtctr %r5
|
||||
bctrl
|
||||
|
||||
/* Now set the MSR back */
|
||||
lis %r6,rtas_regsave@ha
|
||||
lwz %r6,rtas_regsave@l(%r6)
|
||||
mtmsr %r6
|
||||
isync
|
||||
|
||||
/* And return */
|
||||
lwz %r0,4(%r1)
|
||||
mtlr %r0
|
||||
blr
|
||||
|
290
sys/powerpc/ofw/ofwcall64.S
Normal file
290
sys/powerpc/ofw/ofwcall64.S
Normal file
@ -0,0 +1,290 @@
|
||||
/*-
|
||||
* Copyright (C) 2009-2011 Nathan Whitehorn
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <machine/trap.h>
|
||||
#include <machine/param.h>
|
||||
#include <machine/spr.h>
|
||||
#include <machine/asm.h>
|
||||
|
||||
#define OFWSTKSZ 4096 /* 4K Open Firmware stack */
|
||||
|
||||
/*
|
||||
* Globals
|
||||
*/
|
||||
.data
|
||||
.align 4
|
||||
ofwstk:
|
||||
.space OFWSTKSZ
|
||||
rtas_regsave:
|
||||
.space 24 /* 3 * sizeof(register_t) */
|
||||
GLOBAL(ofmsr)
|
||||
.llong 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
|
||||
GLOBAL(rtasmsr)
|
||||
.llong 0
|
||||
GLOBAL(openfirmware_entry)
|
||||
.llong 0 /* Open Firmware entry point */
|
||||
GLOBAL(rtas_entry)
|
||||
.llong 0 /* RTAS entry point */
|
||||
|
||||
/*
|
||||
* Open Firmware Real-mode Entry Point. This is a huge pain.
|
||||
*/
|
||||
|
||||
ASENTRY(ofwcall)
|
||||
mflr %r0
|
||||
std %r0,16(%r1)
|
||||
stdu %r1,-208(%r1)
|
||||
|
||||
/*
|
||||
* We need to save the following, because OF's register save/
|
||||
* restore code assumes that the contents of registers are
|
||||
* at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
|
||||
* get placed in that order in the stack.
|
||||
*/
|
||||
|
||||
mfcr %r4
|
||||
std %r4,48(%r1)
|
||||
std %r13,56(%r1)
|
||||
std %r14,64(%r1)
|
||||
std %r15,72(%r1)
|
||||
std %r16,80(%r1)
|
||||
std %r17,88(%r1)
|
||||
std %r18,96(%r1)
|
||||
std %r19,104(%r1)
|
||||
std %r20,112(%r1)
|
||||
std %r21,120(%r1)
|
||||
std %r22,128(%r1)
|
||||
std %r23,136(%r1)
|
||||
std %r24,144(%r1)
|
||||
std %r25,152(%r1)
|
||||
std %r26,160(%r1)
|
||||
std %r27,168(%r1)
|
||||
std %r28,176(%r1)
|
||||
std %r29,184(%r1)
|
||||
std %r30,192(%r1)
|
||||
std %r31,200(%r1)
|
||||
|
||||
/* Record the old MSR */
|
||||
mfmsr %r6
|
||||
|
||||
/* read client interface handler */
|
||||
lis %r4,openfirmware_entry@ha
|
||||
ld %r4,openfirmware_entry@l(%r4)
|
||||
|
||||
/*
|
||||
* Set the MSR to the OF value. This has the side effect of disabling
|
||||
* exceptions, which is important for the next few steps.
|
||||
*/
|
||||
|
||||
lis %r5,ofmsr@ha
|
||||
ld %r5,ofmsr@l(%r5)
|
||||
mtmsrd %r5
|
||||
isync
|
||||
|
||||
/*
|
||||
* Set up OF stack. This needs to be accessible in real mode and
|
||||
* use the 32-bit ABI stack frame format. The pointer to the current
|
||||
* kernel stack is placed at the very top of the stack along with
|
||||
* the old MSR so we can get them back later.
|
||||
*/
|
||||
mr %r5,%r1
|
||||
lis %r1,(ofwstk+OFWSTKSZ-32)@ha
|
||||
addi %r1,%r1,(ofwstk+OFWSTKSZ-32)@l
|
||||
std %r5,8(%r1) /* Save real stack pointer */
|
||||
std %r2,16(%r1) /* Save old TOC */
|
||||
std %r6,24(%r1) /* Save old MSR */
|
||||
li %r5,0
|
||||
stw %r5,4(%r1)
|
||||
stw %r5,0(%r1)
|
||||
|
||||
/* Finally, branch to OF */
|
||||
mtctr %r4
|
||||
bctrl
|
||||
|
||||
/* Reload stack pointer and MSR from the OFW stack */
|
||||
ld %r6,24(%r1)
|
||||
ld %r2,16(%r1)
|
||||
ld %r1,8(%r1)
|
||||
|
||||
/* Now set the real MSR */
|
||||
mtmsrd %r6
|
||||
isync
|
||||
|
||||
/* Sign-extend the return value from OF */
|
||||
extsw %r3,%r3
|
||||
|
||||
/* Restore all the non-volatile registers */
|
||||
ld %r5,48(%r1)
|
||||
mtcr %r5
|
||||
ld %r13,56(%r1)
|
||||
ld %r14,64(%r1)
|
||||
ld %r15,72(%r1)
|
||||
ld %r16,80(%r1)
|
||||
ld %r17,88(%r1)
|
||||
ld %r18,96(%r1)
|
||||
ld %r19,104(%r1)
|
||||
ld %r20,112(%r1)
|
||||
ld %r21,120(%r1)
|
||||
ld %r22,128(%r1)
|
||||
ld %r23,136(%r1)
|
||||
ld %r24,144(%r1)
|
||||
ld %r25,152(%r1)
|
||||
ld %r26,160(%r1)
|
||||
ld %r27,168(%r1)
|
||||
ld %r28,176(%r1)
|
||||
ld %r29,184(%r1)
|
||||
ld %r30,192(%r1)
|
||||
ld %r31,200(%r1)
|
||||
|
||||
/* Restore the stack and link register */
|
||||
ld %r1,0(%r1)
|
||||
ld %r0,16(%r1)
|
||||
mtlr %r0
|
||||
blr
|
||||
|
||||
/*
|
||||
* RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
|
||||
* stack)
|
||||
*
|
||||
* C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
|
||||
*/
|
||||
|
||||
ASENTRY(rtascall)
|
||||
mflr %r0
|
||||
std %r0,16(%r1)
|
||||
stdu %r1,-208(%r1)
|
||||
|
||||
/*
|
||||
* We need to save the following, because RTAS's register save/
|
||||
* restore code assumes that the contents of registers are
|
||||
* at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
|
||||
* get placed in that order in the stack.
|
||||
*/
|
||||
|
||||
mfcr %r5
|
||||
std %r5,48(%r1)
|
||||
std %r13,56(%r1)
|
||||
std %r14,64(%r1)
|
||||
std %r15,72(%r1)
|
||||
std %r16,80(%r1)
|
||||
std %r17,88(%r1)
|
||||
std %r18,96(%r1)
|
||||
std %r19,104(%r1)
|
||||
std %r20,112(%r1)
|
||||
std %r21,120(%r1)
|
||||
std %r22,128(%r1)
|
||||
std %r23,136(%r1)
|
||||
std %r24,144(%r1)
|
||||
std %r25,152(%r1)
|
||||
std %r26,160(%r1)
|
||||
std %r27,168(%r1)
|
||||
std %r28,176(%r1)
|
||||
std %r29,184(%r1)
|
||||
std %r30,192(%r1)
|
||||
std %r31,200(%r1)
|
||||
|
||||
/* Record the old MSR */
|
||||
mfmsr %r6
|
||||
|
||||
/* read client interface handler */
|
||||
lis %r5,rtas_entry@ha
|
||||
ld %r5,rtas_entry@l(%r5)
|
||||
|
||||
/*
|
||||
* Set the MSR to the RTAS value. This has the side effect of disabling
|
||||
* exceptions, which is important for the next few steps.
|
||||
*/
|
||||
|
||||
lis %r7,rtasmsr@ha
|
||||
ld %r7,rtasmsr@l(%r7)
|
||||
mtmsrd %r7
|
||||
isync
|
||||
|
||||
/*
|
||||
* Set up RTAS register save area, so that we can get back all of
|
||||
* our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
|
||||
* Put this in r1, since RTAS is obliged to save it. Kernel globals
|
||||
* are below 4 GB, so this is safe.
|
||||
*/
|
||||
mr %r7,%r1
|
||||
lis %r1,rtas_regsave@ha
|
||||
addi %r1,%r1,rtas_regsave@l
|
||||
std %r7,0(%r1) /* Save 64-bit stack pointer */
|
||||
std %r2,8(%r1) /* Save TOC */
|
||||
std %r6,16(%r1) /* Save MSR */
|
||||
|
||||
/* Finally, branch to RTAS */
|
||||
mtctr %r5
|
||||
bctrl
|
||||
|
||||
/*
|
||||
* Reload stack pointer and MSR from the reg save area in r1. We are
|
||||
* running in 32-bit mode at this point, so it doesn't matter if r1
|
||||
* has become sign-extended.
|
||||
*/
|
||||
ld %r6,16(%r1)
|
||||
ld %r2,8(%r1)
|
||||
ld %r1,0(%r1)
|
||||
|
||||
/* Now set the real MSR */
|
||||
mtmsrd %r6
|
||||
isync
|
||||
|
||||
/* Sign-extend the return value from RTAS */
|
||||
extsw %r3,%r3
|
||||
|
||||
/* Restore all the non-volatile registers */
|
||||
ld %r5,48(%r1)
|
||||
mtcr %r5
|
||||
ld %r13,56(%r1)
|
||||
ld %r14,64(%r1)
|
||||
ld %r15,72(%r1)
|
||||
ld %r16,80(%r1)
|
||||
ld %r17,88(%r1)
|
||||
ld %r18,96(%r1)
|
||||
ld %r19,104(%r1)
|
||||
ld %r20,112(%r1)
|
||||
ld %r21,120(%r1)
|
||||
ld %r22,128(%r1)
|
||||
ld %r23,136(%r1)
|
||||
ld %r24,144(%r1)
|
||||
ld %r25,152(%r1)
|
||||
ld %r26,160(%r1)
|
||||
ld %r27,168(%r1)
|
||||
ld %r28,176(%r1)
|
||||
ld %r29,184(%r1)
|
||||
ld %r30,192(%r1)
|
||||
ld %r31,200(%r1)
|
||||
|
||||
/* Restore the stack and link register */
|
||||
ld %r1,0(%r1)
|
||||
ld %r0,16(%r1)
|
||||
mtlr %r0
|
||||
blr
|
||||
|
243
sys/powerpc/ofw/rtas.c
Normal file
243
sys/powerpc/ofw/rtas.c
Normal file
@ -0,0 +1,243 @@
|
||||
/*-
|
||||
* Copyright (c) 2011 Nathan Whitehorn
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/pmap.h>
|
||||
#include <machine/rtas.h>
|
||||
#include <machine/stdarg.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
MALLOC_DEFINE(M_RTAS, "rtas", "Run Time Abstraction Service");
|
||||
|
||||
static vm_offset_t rtas_bounce_phys;
|
||||
static caddr_t rtas_bounce_virt;
|
||||
static off_t rtas_bounce_offset;
|
||||
static size_t rtas_bounce_size;
|
||||
static uintptr_t rtas_private_data;
|
||||
static struct mtx rtas_mtx;
|
||||
static phandle_t rtas;
|
||||
|
||||
/* From ofwcall.S */
|
||||
int rtascall(vm_offset_t callbuffer, uintptr_t rtas_privdat);
|
||||
extern uintptr_t rtas_entry;
|
||||
extern register_t rtasmsr;
|
||||
|
||||
/*
|
||||
* After the VM is up, allocate RTAS memory and instantiate it
|
||||
*/
|
||||
|
||||
static void rtas_setup(void *);
|
||||
|
||||
SYSINIT(rtas_setup, SI_SUB_KMEM, SI_ORDER_ANY, rtas_setup, NULL);
|
||||
|
||||
static void
|
||||
rtas_setup(void *junk)
|
||||
{
|
||||
ihandle_t rtasi;
|
||||
cell_t rtas_size = 0, rtas_ptr;
|
||||
char path[31];
|
||||
int result;
|
||||
|
||||
rtas = OF_finddevice("/rtas");
|
||||
if (rtas == -1) {
|
||||
rtas = 0;
|
||||
return;
|
||||
}
|
||||
OF_package_to_path(rtas, path, sizeof(path));
|
||||
rtasi = OF_open(path);
|
||||
if (rtasi == 0) {
|
||||
rtas = 0;
|
||||
printf("Error initializing RTAS: could not open node\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mtx_init(&rtas_mtx, "RTAS", MTX_DEF, 0);
|
||||
|
||||
/* RTAS must be called with everything turned off in MSR */
|
||||
rtasmsr = mfmsr();
|
||||
rtasmsr &= ~(PSL_IR | PSL_DR | PSL_EE | PSL_SE);
|
||||
#ifdef __powerpc64__
|
||||
rtasmsr &= ~PSL_SF;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocate rtas_size + one page of contiguous, wired physical memory
|
||||
* that can fit into a 32-bit address space and accessed from real mode.
|
||||
* This is used both to bounce arguments and for RTAS private data.
|
||||
*
|
||||
* It must be 4KB-aligned and not cross a 256 MB boundary.
|
||||
*/
|
||||
|
||||
OF_getprop(rtas, "rtas-size", &rtas_size, sizeof(rtas_size));
|
||||
rtas_size = round_page(rtas_size);
|
||||
rtas_bounce_virt = contigmalloc(rtas_size + PAGE_SIZE, M_RTAS, 0, 0,
|
||||
ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT),
|
||||
4096, 256*1024*1024);
|
||||
|
||||
rtas_private_data = vtophys(rtas_bounce_virt);
|
||||
rtas_bounce_virt += rtas_size; /* Actual bounce area */
|
||||
rtas_bounce_phys = vtophys(rtas_bounce_virt);
|
||||
rtas_bounce_size = PAGE_SIZE;
|
||||
|
||||
/*
|
||||
* Instantiate RTAS. We always use the 32-bit version.
|
||||
*/
|
||||
|
||||
result = OF_call_method("instantiate-rtas", rtasi, 1, 1,
|
||||
(cell_t)rtas_private_data, &rtas_ptr);
|
||||
OF_close(rtasi);
|
||||
|
||||
if (result != 0) {
|
||||
rtas = 0;
|
||||
rtas_ptr = 0;
|
||||
printf("Error initializing RTAS (%d)\n", result);
|
||||
return;
|
||||
}
|
||||
|
||||
rtas_entry = (uintptr_t)(rtas_ptr);
|
||||
}
|
||||
|
||||
static cell_t
|
||||
rtas_real_map(const void *buf, size_t len)
|
||||
{
|
||||
cell_t phys;
|
||||
|
||||
mtx_assert(&rtas_mtx, MA_OWNED);
|
||||
|
||||
/*
|
||||
* Make sure the bounce page offset satisfies any reasonable
|
||||
* alignment constraint.
|
||||
*/
|
||||
rtas_bounce_offset += sizeof(register_t) -
|
||||
(rtas_bounce_offset % sizeof(register_t));
|
||||
|
||||
if (rtas_bounce_offset + len > rtas_bounce_size) {
|
||||
panic("Oversize RTAS call!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (buf != NULL)
|
||||
memcpy(rtas_bounce_virt + rtas_bounce_offset, buf, len);
|
||||
else
|
||||
return (0);
|
||||
|
||||
phys = rtas_bounce_phys + rtas_bounce_offset;
|
||||
rtas_bounce_offset += len;
|
||||
|
||||
return (phys);
|
||||
}
|
||||
|
||||
static void
|
||||
rtas_real_unmap(cell_t physaddr, void *buf, size_t len)
|
||||
{
|
||||
mtx_assert(&rtas_mtx, MA_OWNED);
|
||||
|
||||
if (physaddr == 0)
|
||||
return;
|
||||
|
||||
memcpy(buf, rtas_bounce_virt + (physaddr - rtas_bounce_phys), len);
|
||||
}
|
||||
|
||||
/* Check if we have RTAS */
|
||||
int
|
||||
rtas_exists(void)
|
||||
{
|
||||
return (rtas != 0);
|
||||
}
|
||||
|
||||
/* Call an RTAS method by token */
|
||||
int
|
||||
rtas_call_method(cell_t token, int nargs, int nreturns, ...)
|
||||
{
|
||||
vm_offset_t argsptr;
|
||||
va_list ap;
|
||||
struct {
|
||||
cell_t token;
|
||||
cell_t nargs;
|
||||
cell_t nreturns;
|
||||
cell_t args_n_results[12];
|
||||
} args;
|
||||
int n, result;
|
||||
|
||||
if (!rtas_exists() || nargs + nreturns > 12)
|
||||
return (-1);
|
||||
|
||||
args.token = token;
|
||||
va_start(ap, nreturns);
|
||||
|
||||
mtx_lock(&rtas_mtx);
|
||||
rtas_bounce_offset = 0;
|
||||
|
||||
args.nargs = nargs;
|
||||
args.nreturns = nreturns;
|
||||
|
||||
for (n = 0; n < nargs; n++)
|
||||
args.args_n_results[n] = va_arg(ap, cell_t);
|
||||
|
||||
argsptr = rtas_real_map(&args, sizeof(args));
|
||||
result = rtascall(argsptr, rtas_private_data);
|
||||
rtas_real_unmap(argsptr, &args, sizeof(args));
|
||||
mtx_unlock(&rtas_mtx);
|
||||
|
||||
if (result < 0)
|
||||
return (result);
|
||||
|
||||
for (n = nargs; n < nargs + nreturns; n++)
|
||||
*va_arg(ap, cell_t *) = args.args_n_results[n];
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Look up an RTAS token */
|
||||
cell_t
|
||||
rtas_token_lookup(const char *method)
|
||||
{
|
||||
cell_t token;
|
||||
|
||||
if (!rtas_exists())
|
||||
return (-1);
|
||||
|
||||
if (OF_getprop(rtas, method, &token, sizeof(token)) == -1)
|
||||
return (-1);
|
||||
|
||||
return (token);
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 1, 2010
|
||||
.Dd June 3, 2011
|
||||
.Dt MAN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -73,8 +73,12 @@ environment variable.
|
||||
.It Fl P Ar pager
|
||||
Use specified pager.
|
||||
Defaults to
|
||||
.Ic "less -sR"
|
||||
if color support is enabled, or
|
||||
.Ic "more -s" .
|
||||
Overrides the
|
||||
.Ev MANPAGER
|
||||
environment variable, which in turn overrides the
|
||||
.Ev PAGER
|
||||
environment variable.
|
||||
.It Fl S Ar mansect
|
||||
@ -283,9 +287,25 @@ Restricts manual sections searched to the specified colon delimited list.
|
||||
Corresponds to the
|
||||
.Fl S
|
||||
option.
|
||||
.It Ev PAGER
|
||||
.It Ev MANWIDTH
|
||||
If set to a numeric value, used as the width manpages should be displayed.
|
||||
Otherwise, if set to a special value
|
||||
.Dq Li tty ,
|
||||
and output is to a terminal,
|
||||
the pages may be displayed over the whole width of the screen.
|
||||
.It Ev MANCOLOR
|
||||
If set, enables color support.
|
||||
.It Ev MANPAGER
|
||||
Program used to display files.
|
||||
If unset,
|
||||
.Pp
|
||||
If unset, and color support is enabled,
|
||||
.Ic "less -sR"
|
||||
is used.
|
||||
.Pp
|
||||
If unset, and color support is disabled, then
|
||||
.Ev PAGER
|
||||
is used.
|
||||
If that has no value either,
|
||||
.Ic "more -s"
|
||||
is used.
|
||||
.El
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 1, 2010
|
||||
.Dd June 3, 2011
|
||||
.Os
|
||||
.Dt MAN.CONF 5
|
||||
.Sh NAME
|
||||
@ -72,7 +72,6 @@ For pages in a given language, overriding the default toolset for
|
||||
display is supported via the following definitions:
|
||||
.Bl -tag -offset indent -compact
|
||||
.It EQN Ns _ Ns Va LANG
|
||||
.It COL Ns _ Ns Va LANG
|
||||
.It NROFF Ns _ Ns Va LANG
|
||||
.It PIC Ns _ Ns Va LANG
|
||||
.It TBL Ns _ Ns Va LANG
|
||||
@ -112,7 +111,7 @@ with the following contents:
|
||||
.Bd -literal -offset indent
|
||||
# Setup Japanese toolset
|
||||
MANLOCALE ja_JP.eucJP
|
||||
EQN_JA /usr/local/bin/gepn
|
||||
EQN_JA /usr/local/bin/geqn
|
||||
PIC_JA /usr/local/bin/gpic
|
||||
TBL_JA /usr/local/bin/gtbl
|
||||
NROFF_JA /usr/local/bin/groff -man -dlang=ja_JP.eucJP
|
||||
|
@ -112,7 +112,11 @@ check_man() {
|
||||
setup_cattool $manpage
|
||||
decho " Found manpage $manpage"
|
||||
|
||||
if exists "$2" && is_newer $found $manpage; then
|
||||
if [ -n "${use_width}" ]; then
|
||||
# non-standard width
|
||||
unset use_cat
|
||||
decho " Skipping catpage: non-standard page width"
|
||||
elif exists "$2" && is_newer $found $manpage; then
|
||||
# cat page found and is newer, use that
|
||||
use_cat=yes
|
||||
catpage=$found
|
||||
@ -275,7 +279,7 @@ man_check_for_so() {
|
||||
# Usage: man_display_page
|
||||
# Display either the manpage or catpage depending on the use_cat variable
|
||||
man_display_page() {
|
||||
local EQN COL NROFF PIC TBL TROFF REFER VGRIND
|
||||
local EQN NROFF PIC TBL TROFF REFER VGRIND
|
||||
local IFS l nroff_dev pipeline preproc_arg tool
|
||||
|
||||
# We are called with IFS set to colon. This causes really weird
|
||||
@ -290,10 +294,10 @@ man_display_page() {
|
||||
ret=0
|
||||
else
|
||||
if [ $debug -gt 0 ]; then
|
||||
decho "Command: $cattool $catpage | $PAGER"
|
||||
decho "Command: $cattool $catpage | $MANPAGER"
|
||||
ret=0
|
||||
else
|
||||
eval "$cattool $catpage | $PAGER"
|
||||
eval "$cattool $catpage | $MANPAGER"
|
||||
ret=$?
|
||||
fi
|
||||
fi
|
||||
@ -343,7 +347,7 @@ man_display_page() {
|
||||
# Allow language specific calls to override the default
|
||||
# set of utilities.
|
||||
l=$(echo $man_lang | tr [:lower:] [:upper:])
|
||||
for tool in EQN COL NROFF PIC TBL TROFF REFER VGRIND; do
|
||||
for tool in EQN NROFF PIC TBL TROFF REFER VGRIND; do
|
||||
eval "$tool=\${${tool}_$l:-\$$tool}"
|
||||
done
|
||||
;;
|
||||
@ -352,6 +356,14 @@ man_display_page() {
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$MANCOLOR" ]; then
|
||||
NROFF="$NROFF -P-c"
|
||||
fi
|
||||
|
||||
if [ -n "${use_width}" ]; then
|
||||
NROFF="$NROFF -rLL=${use_width}n -rLT=${use_width}n"
|
||||
fi
|
||||
|
||||
if [ -n "$MANROFFSEQ" ]; then
|
||||
set -- -$MANROFFSEQ
|
||||
while getopts 'egprtv' preproc_arg; do
|
||||
@ -360,7 +372,7 @@ man_display_page() {
|
||||
g) ;; # Ignore for compatability.
|
||||
p) pipeline="$pipeline | $PIC" ;;
|
||||
r) pipeline="$pipeline | $REFER" ;;
|
||||
t) pipeline="$pipeline | $TBL"; use_col=yes ;;
|
||||
t) pipeline="$pipeline | $TBL" ;;
|
||||
v) pipeline="$pipeline | $VGRIND" ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
@ -369,19 +381,12 @@ man_display_page() {
|
||||
pipeline="${pipeline#" | "}"
|
||||
else
|
||||
pipeline="$TBL"
|
||||
use_col=yes
|
||||
fi
|
||||
|
||||
if [ -n "$tflag" ]; then
|
||||
pipeline="$pipeline | $TROFF"
|
||||
else
|
||||
pipeline="$pipeline | $NROFF"
|
||||
|
||||
if [ -n "$use_col" ]; then
|
||||
pipeline="$pipeline | $COL"
|
||||
fi
|
||||
|
||||
pipeline="$pipeline | $PAGER"
|
||||
pipeline="$pipeline | $NROFF | $MANPAGER"
|
||||
fi
|
||||
|
||||
if [ $debug -gt 0 ]; then
|
||||
@ -483,7 +488,7 @@ man_parse_args() {
|
||||
while getopts 'M:P:S:adfhkm:op:tw' cmd_arg; do
|
||||
case "${cmd_arg}" in
|
||||
M) MANPATH=$OPTARG ;;
|
||||
P) PAGER=$OPTARG ;;
|
||||
P) MANPAGER=$OPTARG ;;
|
||||
S) MANSECT=$OPTARG ;;
|
||||
a) aflag=aflag ;;
|
||||
d) debug=$(( $debug + 1 )) ;;
|
||||
@ -562,6 +567,35 @@ man_setup() {
|
||||
|
||||
build_manpath
|
||||
man_setup_locale
|
||||
man_setup_width
|
||||
}
|
||||
|
||||
# Usage: man_setup_width
|
||||
# Set up page width.
|
||||
man_setup_width() {
|
||||
local sizes
|
||||
|
||||
unset use_width
|
||||
case "$MANWIDTH" in
|
||||
[0-9]*)
|
||||
if [ "$MANWIDTH" -gt 0 2>/dev/null ]; then
|
||||
use_width=$MANWIDTH
|
||||
fi
|
||||
;;
|
||||
[Tt][Tt][Yy])
|
||||
if { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1; then
|
||||
set -- $sizes
|
||||
if [ $2 -gt 80 ]; then
|
||||
use_width=$(($2-2))
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if [ -n "$use_width" ]; then
|
||||
decho "Using non-standard page width: ${use_width}"
|
||||
else
|
||||
decho 'Using standard page width'
|
||||
fi
|
||||
}
|
||||
|
||||
# Usage: man_setup_locale
|
||||
@ -667,7 +701,7 @@ parse_file() {
|
||||
manlocales="$manlocales:$tstr"
|
||||
;;
|
||||
MANCONFIG*) decho " MANCONFIG" 3
|
||||
trim "${line#MANCONF}"
|
||||
trim "${line#MANCONFIG}"
|
||||
config_local="$tstr"
|
||||
;;
|
||||
# Set variables in the form of FOO_BAR
|
||||
@ -778,7 +812,7 @@ search_whatis() {
|
||||
bad=${bad#\\n}
|
||||
|
||||
if [ -n "$good" ]; then
|
||||
echo -e "$good" | $PAGER
|
||||
echo -e "$good" | $MANPAGER
|
||||
fi
|
||||
|
||||
if [ -n "$bad" ]; then
|
||||
@ -802,13 +836,21 @@ setup_cattool() {
|
||||
}
|
||||
|
||||
# Usage: setup_pager
|
||||
# Correctly sets $PAGER
|
||||
# Correctly sets $MANPAGER
|
||||
setup_pager() {
|
||||
# Setup pager.
|
||||
if [ -z "$PAGER" ]; then
|
||||
PAGER="more -s"
|
||||
if [ -z "$MANPAGER" ]; then
|
||||
if [ -n "$MANCOLOR" ]; then
|
||||
MANPAGER="less -sR"
|
||||
else
|
||||
if [ -n "$PAGER" ]; then
|
||||
MANPAGER="$PAGER"
|
||||
else
|
||||
MANPAGER="more -s"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
decho "Using pager: $PAGER"
|
||||
decho "Using pager: $MANPAGER"
|
||||
}
|
||||
|
||||
# Usage: trim string
|
||||
@ -891,15 +933,15 @@ do_whatis() {
|
||||
|
||||
# User's PATH setting decides on the groff-suite to pick up.
|
||||
EQN=eqn
|
||||
NROFF='groff -S -P-c -Wall -mtty-char -man'
|
||||
NROFF='groff -S -P-h -Wall -mtty-char -man'
|
||||
PIC=pic
|
||||
REFER=refer
|
||||
TBL=tbl
|
||||
TROFF='groff -S -man'
|
||||
VGRIND=vgrind
|
||||
|
||||
COL=/usr/bin/col
|
||||
LOCALE=/usr/bin/locale
|
||||
STTY=/bin/stty
|
||||
SYSCTL=/sbin/sysctl
|
||||
|
||||
debug=0
|
||||
|
@ -41,8 +41,6 @@ DIALOG_TAGS=""
|
||||
: ${DIALOG_ITEM_HELP=4}
|
||||
: ${DIALOG_ESC=255}
|
||||
|
||||
echo -n > $BSDINSTALL_TMPETC/rc.conf.net
|
||||
|
||||
for IF in `ifconfig -l`; do
|
||||
test "$IF" = "lo0" && continue
|
||||
(ifconfig -g wlan | egrep -wq $IF) && continue
|
||||
@ -56,12 +54,14 @@ INTERFACE=`echo $DIALOG_TAGS | xargs dialog --backtitle 'FreeBSD Installer' --ti
|
||||
if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi
|
||||
exec 3>&-
|
||||
|
||||
: > $BSDINSTALL_TMPETC/._rc.conf.net
|
||||
|
||||
# Do a dirty check to see if this a wireless interface -- there should be a
|
||||
# better way
|
||||
IFCONFIG_PREFIX=""
|
||||
if ifconfig $INTERFACE | grep -q 'media: IEEE 802.11 Wireless'; then
|
||||
NEXT_WLAN_IFACE=wlan0 # XXX
|
||||
echo wlans_$INTERFACE=\"$NEXT_WLAN_IFACE\" >> $BSDINSTALL_TMPETC/rc.conf.net
|
||||
echo wlans_$INTERFACE=\"$NEXT_WLAN_IFACE\" >> $BSDINSTALL_TMPETC/._rc.conf.net
|
||||
IFCONFIG_PREFIX="WPA "
|
||||
if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
|
||||
ifconfig $NEXT_WLAN_IFACE create wlandev $INTERFACE
|
||||
@ -95,7 +95,7 @@ fi
|
||||
# In case wlanconfig left an option and we do not support IPv4 we need to write
|
||||
# it out on its own. We cannot write it out with IPv6 as that suffix.
|
||||
if [ ${IPV4_AVAIL} -eq 0 -a -n ${IFCONFIG_PREFIX} ]; then
|
||||
echo ifconfig_${INTERFACE}=\"${IFCONFIG_PREFIX}\" >> $BSDINSTALL_TMPETC/rc.conf.net
|
||||
echo ifconfig_${INTERFACE}=\"${IFCONFIG_PREFIX}\" >> $BSDINSTALL_TMPETC/._rc.conf.net
|
||||
fi
|
||||
if [ ${IPV6_AVAIL} -eq 1 ]; then
|
||||
dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \
|
||||
@ -192,3 +192,4 @@ BEGIN {
|
||||
printf "nameserver %s\n", $1;
|
||||
}' > ${BSDINSTALL_TMPETC}/resolv.conf
|
||||
|
||||
mv $BSDINSTALL_TMPETC/._rc.conf.net $BSDINSTALL_TMPETC/rc.conf.net
|
||||
|
@ -44,7 +44,7 @@ esac
|
||||
|
||||
dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --yesno 'Would you like to use DHCP to configure this interface?' 0 0
|
||||
if [ $? -eq $DIALOG_OK ]; then
|
||||
echo ifconfig_$INTERFACE=\"${IFCONFIG_PREFIX}DHCP\" >> $BSDINSTALL_TMPETC/rc.conf.net
|
||||
echo ifconfig_$INTERFACE=\"${IFCONFIG_PREFIX}DHCP\" >> $BSDINSTALL_TMPETC/._rc.conf.net
|
||||
|
||||
if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
|
||||
dialog --backtitle 'FreeBSD Installer' --infobox "Acquiring DHCP lease..." 0 0
|
||||
@ -74,10 +74,10 @@ echo $INTERFACE $IF_CONFIG |
|
||||
awk -v prefix="$IFCONFIG_PREFIX" '{
|
||||
printf("ifconfig_%s=\"%s inet %s netmask %s\"\n", $1, prefix, $2, $3);
|
||||
printf("defaultrouter=\"%s\"\n", $4);
|
||||
}' >> $BSDINSTALL_TMPETC/rc.conf.net
|
||||
}' >> $BSDINSTALL_TMPETC/._rc.conf.net
|
||||
|
||||
if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
|
||||
. $BSDINSTALL_TMPETC/rc.conf.net
|
||||
. $BSDINSTALL_TMPETC/._rc.conf.net
|
||||
ifconfig $INTERFACE inet `eval echo \\\$ifconfig_$INTERFACE`
|
||||
route delete -inet default
|
||||
route add -inet default $defaultrouter
|
||||
|
@ -69,7 +69,7 @@ while : ; do
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
echo ifconfig_${INTERFACE}_ipv6=\"inet6 accept_rtadv\" >> $BSDINSTALL_TMPETC/rc.conf.net
|
||||
echo ifconfig_${INTERFACE}_ipv6=\"inet6 accept_rtadv\" >> $BSDINSTALL_TMPETC/._rc.conf.net
|
||||
exit 0
|
||||
else
|
||||
break
|
||||
@ -138,10 +138,10 @@ BEGIN {
|
||||
sub("$", "/64", $1);
|
||||
}
|
||||
printf("ifconfig_%s_ipv6=\"inet6 %s\"\n", iface, $1);
|
||||
}' >> $BSDINSTALL_TMPETC/rc.conf.net
|
||||
}' >> $BSDINSTALL_TMPETC/._rc.conf.net
|
||||
|
||||
if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
|
||||
. $BSDINSTALL_TMPETC/rc.conf.net
|
||||
. $BSDINSTALL_TMPETC/._rc.conf.net
|
||||
ifconfig ${INTERFACE} `eval echo \\\$ifconfig_${INTERFACE}_ipv6`
|
||||
route delete default
|
||||
route add default ${ipv6_defaultrouter}
|
||||
|
@ -158,6 +158,8 @@ struct fhreturn {
|
||||
int *fhr_secflavors;
|
||||
};
|
||||
|
||||
#define GETPORT_MAXTRY 20 /* Max tries to get a port # */
|
||||
|
||||
/* Global defs */
|
||||
char *add_expdir(struct dirlist **, char *, int);
|
||||
void add_dlist(struct dirlist **, struct dirlist *,
|
||||
@ -167,7 +169,9 @@ int check_dirpath(char *);
|
||||
int check_options(struct dirlist *);
|
||||
int checkmask(struct sockaddr *sa);
|
||||
int chk_host(struct dirlist *, struct sockaddr *, int *, int *);
|
||||
void create_service(struct netconfig *nconf);
|
||||
static int create_service(struct netconfig *nconf);
|
||||
static void complete_service(struct netconfig *nconf, char *port_str);
|
||||
static void clearout_service(void);
|
||||
void del_mlist(char *hostp, char *dirp);
|
||||
struct dirlist *dirp_search(struct dirlist *, char *);
|
||||
int do_mount(struct exportlist *, struct grouplist *, int,
|
||||
@ -233,6 +237,10 @@ int got_sighup = 0;
|
||||
int xcreated = 0;
|
||||
|
||||
char *svcport_str = NULL;
|
||||
static int mallocd_svcport = 0;
|
||||
static int *sock_fd;
|
||||
static int sock_fdcnt;
|
||||
static int sock_fdpos;
|
||||
|
||||
int opt_flags;
|
||||
static int have_v6 = 1;
|
||||
@ -281,6 +289,8 @@ main(int argc, char **argv)
|
||||
in_port_t svcport;
|
||||
int c, k, s;
|
||||
int maxrec = RPC_MAXDATASIZE;
|
||||
int attempt_cnt, port_len, port_pos, ret;
|
||||
char **port_list;
|
||||
|
||||
/* Check that another mountd isn't already running. */
|
||||
pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
|
||||
@ -451,17 +461,97 @@ main(int argc, char **argv)
|
||||
hosts[nhosts - 1] = "127.0.0.1";
|
||||
}
|
||||
|
||||
attempt_cnt = 1;
|
||||
sock_fdcnt = 0;
|
||||
sock_fd = NULL;
|
||||
port_list = NULL;
|
||||
port_len = 0;
|
||||
nc_handle = setnetconfig();
|
||||
while ((nconf = getnetconfig(nc_handle))) {
|
||||
if (nconf->nc_flag & NC_VISIBLE) {
|
||||
if (have_v6 == 0 && strcmp(nconf->nc_protofmly,
|
||||
"inet6") == 0) {
|
||||
/* DO NOTHING */
|
||||
} else {
|
||||
ret = create_service(nconf);
|
||||
if (ret == 1)
|
||||
/* Ignore this call */
|
||||
continue;
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* Failed to bind port, so close off
|
||||
* all sockets created and try again
|
||||
* if the port# was dynamically
|
||||
* assigned via bind(2).
|
||||
*/
|
||||
clearout_service();
|
||||
if (mallocd_svcport != 0 &&
|
||||
attempt_cnt < GETPORT_MAXTRY) {
|
||||
free(svcport_str);
|
||||
svcport_str = NULL;
|
||||
mallocd_svcport = 0;
|
||||
} else {
|
||||
errno = EADDRINUSE;
|
||||
syslog(LOG_ERR,
|
||||
"bindresvport_sa: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Start over at the first service. */
|
||||
free(sock_fd);
|
||||
sock_fdcnt = 0;
|
||||
sock_fd = NULL;
|
||||
nc_handle = setnetconfig();
|
||||
attempt_cnt++;
|
||||
} else if (mallocd_svcport != 0 &&
|
||||
attempt_cnt == GETPORT_MAXTRY) {
|
||||
/*
|
||||
* For the last attempt, allow
|
||||
* different port #s for each nconf
|
||||
* by saving the svcport_str and
|
||||
* setting it back to NULL.
|
||||
*/
|
||||
port_list = realloc(port_list,
|
||||
(port_len + 1) * sizeof(char *));
|
||||
if (port_list == NULL)
|
||||
out_of_mem();
|
||||
port_list[port_len++] = svcport_str;
|
||||
svcport_str = NULL;
|
||||
mallocd_svcport = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Successfully bound the ports, so call complete_service() to
|
||||
* do the rest of the setup on the service(s).
|
||||
*/
|
||||
sock_fdpos = 0;
|
||||
port_pos = 0;
|
||||
nc_handle = setnetconfig();
|
||||
while ((nconf = getnetconfig(nc_handle))) {
|
||||
if (nconf->nc_flag & NC_VISIBLE) {
|
||||
if (have_v6 == 0 && strcmp(nconf->nc_protofmly,
|
||||
"inet6") == 0) {
|
||||
/* DO NOTHING */
|
||||
} else if (port_list != NULL) {
|
||||
if (port_pos >= port_len) {
|
||||
syslog(LOG_ERR, "too many port#s");
|
||||
exit(1);
|
||||
}
|
||||
complete_service(nconf, port_list[port_pos++]);
|
||||
} else
|
||||
create_service(nconf);
|
||||
complete_service(nconf, svcport_str);
|
||||
}
|
||||
}
|
||||
endnetconfig(nc_handle);
|
||||
free(sock_fd);
|
||||
if (port_list != NULL) {
|
||||
for (port_pos = 0; port_pos < port_len; port_pos++)
|
||||
free(port_list[port_pos]);
|
||||
free(port_list);
|
||||
}
|
||||
|
||||
if (xcreated == 0) {
|
||||
syslog(LOG_ERR, "could not create any services");
|
||||
@ -491,30 +581,31 @@ main(int argc, char **argv)
|
||||
|
||||
/*
|
||||
* This routine creates and binds sockets on the appropriate
|
||||
* addresses. It gets called one time for each transport and
|
||||
* registrates the service with rpcbind on that trasport.
|
||||
* addresses. It gets called one time for each transport.
|
||||
* It returns 0 upon success, 1 for ingore the call and -1 to indicate
|
||||
* bind failed with EADDRINUSE.
|
||||
* Any file descriptors that have been created are stored in sock_fd and
|
||||
* the total count of them is maintained in sock_fdcnt.
|
||||
*/
|
||||
void
|
||||
static int
|
||||
create_service(struct netconfig *nconf)
|
||||
{
|
||||
struct addrinfo hints, *res = NULL;
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr_in6 *sin6;
|
||||
struct __rpc_sockinfo si;
|
||||
struct netbuf servaddr;
|
||||
SVCXPRT *transp = NULL;
|
||||
int aicode;
|
||||
int fd;
|
||||
int nhostsbak;
|
||||
int one = 1;
|
||||
int r;
|
||||
int registered = 0;
|
||||
u_int32_t host_addr[4]; /* IPv4 or IPv6 */
|
||||
int mallocd_res;
|
||||
|
||||
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS_ORD))
|
||||
return; /* not my type */
|
||||
return (1); /* not my type */
|
||||
|
||||
/*
|
||||
* XXX - using RPC library internal functions.
|
||||
@ -522,7 +613,7 @@ create_service(struct netconfig *nconf)
|
||||
if (!__rpc_nconf2sockinfo(nconf, &si)) {
|
||||
syslog(LOG_ERR, "cannot get information for %s",
|
||||
nconf->nc_netid);
|
||||
return;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Get mountd's address on this transport */
|
||||
@ -538,6 +629,12 @@ create_service(struct netconfig *nconf)
|
||||
nhostsbak = nhosts;
|
||||
while (nhostsbak > 0) {
|
||||
--nhostsbak;
|
||||
sock_fd = realloc(sock_fd, (sock_fdcnt + 1) * sizeof(int));
|
||||
if (sock_fd == NULL)
|
||||
out_of_mem();
|
||||
sock_fd[sock_fdcnt++] = -1; /* Set invalid for now. */
|
||||
mallocd_res = 0;
|
||||
|
||||
/*
|
||||
* XXX - using RPC library internal functions.
|
||||
*/
|
||||
@ -549,14 +646,16 @@ create_service(struct netconfig *nconf)
|
||||
|
||||
syslog(non_fatal ? LOG_DEBUG : LOG_ERR,
|
||||
"cannot create socket for %s", nconf->nc_netid);
|
||||
return;
|
||||
if (non_fatal != 0)
|
||||
continue;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (hints.ai_family) {
|
||||
case AF_INET:
|
||||
if (inet_pton(AF_INET, hosts[nhostsbak],
|
||||
host_addr) == 1) {
|
||||
hints.ai_flags &= AI_NUMERICHOST;
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
} else {
|
||||
/*
|
||||
* Skip if we have an AF_INET6 address.
|
||||
@ -571,7 +670,7 @@ create_service(struct netconfig *nconf)
|
||||
case AF_INET6:
|
||||
if (inet_pton(AF_INET6, hosts[nhostsbak],
|
||||
host_addr) == 1) {
|
||||
hints.ai_flags &= AI_NUMERICHOST;
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
} else {
|
||||
/*
|
||||
* Skip if we have an AF_INET address.
|
||||
@ -607,6 +706,7 @@ create_service(struct netconfig *nconf)
|
||||
res = malloc(sizeof(struct addrinfo));
|
||||
if (res == NULL)
|
||||
out_of_mem();
|
||||
mallocd_res = 1;
|
||||
res->ai_flags = hints.ai_flags;
|
||||
res->ai_family = hints.ai_family;
|
||||
res->ai_protocol = hints.ai_protocol;
|
||||
@ -620,7 +720,7 @@ create_service(struct netconfig *nconf)
|
||||
sin->sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
res->ai_addr = (struct sockaddr*) sin;
|
||||
res->ai_addrlen = (socklen_t)
|
||||
sizeof(res->ai_addr);
|
||||
sizeof(struct sockaddr_in);
|
||||
break;
|
||||
case AF_INET6:
|
||||
sin6 = malloc(sizeof(struct sockaddr_in6));
|
||||
@ -631,10 +731,12 @@ create_service(struct netconfig *nconf)
|
||||
sin6->sin6_addr = in6addr_any;
|
||||
res->ai_addr = (struct sockaddr*) sin6;
|
||||
res->ai_addrlen = (socklen_t)
|
||||
sizeof(res->ai_addr);
|
||||
break;
|
||||
default:
|
||||
sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR, "bad addr fam %d",
|
||||
res->ai_family);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if ((aicode = getaddrinfo(NULL, svcport_str,
|
||||
@ -643,6 +745,7 @@ create_service(struct netconfig *nconf)
|
||||
"cannot get local address for %s: %s",
|
||||
nconf->nc_netid,
|
||||
gai_strerror(aicode));
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -652,16 +755,91 @@ create_service(struct netconfig *nconf)
|
||||
syslog(LOG_ERR,
|
||||
"cannot get local address for %s: %s",
|
||||
nconf->nc_netid, gai_strerror(aicode));
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the fd. */
|
||||
sock_fd[sock_fdcnt - 1] = fd;
|
||||
|
||||
/* Now, attempt the bind. */
|
||||
r = bindresvport_sa(fd, res->ai_addr);
|
||||
if (r != 0) {
|
||||
if (errno == EADDRINUSE && mallocd_svcport != 0) {
|
||||
if (mallocd_res != 0) {
|
||||
free(res->ai_addr);
|
||||
free(res);
|
||||
} else
|
||||
freeaddrinfo(res);
|
||||
return (-1);
|
||||
}
|
||||
syslog(LOG_ERR, "bindresvport_sa: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (svcport_str == NULL) {
|
||||
svcport_str = malloc(NI_MAXSERV * sizeof(char));
|
||||
if (svcport_str == NULL)
|
||||
out_of_mem();
|
||||
mallocd_svcport = 1;
|
||||
|
||||
if (getnameinfo(res->ai_addr,
|
||||
res->ai_addr->sa_len, NULL, NI_MAXHOST,
|
||||
svcport_str, NI_MAXSERV * sizeof(char),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV))
|
||||
errx(1, "Cannot get port number");
|
||||
}
|
||||
if (mallocd_res != 0) {
|
||||
free(res->ai_addr);
|
||||
free(res);
|
||||
} else
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after all the create_service() calls have succeeded, to complete
|
||||
* the setup and registration.
|
||||
*/
|
||||
static void
|
||||
complete_service(struct netconfig *nconf, char *port_str)
|
||||
{
|
||||
struct addrinfo hints, *res = NULL;
|
||||
struct __rpc_sockinfo si;
|
||||
struct netbuf servaddr;
|
||||
SVCXPRT *transp = NULL;
|
||||
int aicode, fd, nhostsbak;
|
||||
int registered = 0;
|
||||
|
||||
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS_ORD))
|
||||
return; /* not my type */
|
||||
|
||||
/*
|
||||
* XXX - using RPC library internal functions.
|
||||
*/
|
||||
if (!__rpc_nconf2sockinfo(nconf, &si)) {
|
||||
syslog(LOG_ERR, "cannot get information for %s",
|
||||
nconf->nc_netid);
|
||||
return;
|
||||
}
|
||||
|
||||
nhostsbak = nhosts;
|
||||
while (nhostsbak > 0) {
|
||||
--nhostsbak;
|
||||
if (sock_fdpos >= sock_fdcnt) {
|
||||
/* Should never happen. */
|
||||
syslog(LOG_ERR, "Ran out of socket fd's");
|
||||
return;
|
||||
}
|
||||
fd = sock_fd[sock_fdpos++];
|
||||
if (fd < 0)
|
||||
continue;
|
||||
|
||||
if (nconf->nc_semantics != NC_TPI_CLTS)
|
||||
listen(fd, SOMAXCONN);
|
||||
|
||||
@ -696,19 +874,7 @@ create_service(struct netconfig *nconf)
|
||||
hints.ai_socktype = si.si_socktype;
|
||||
hints.ai_protocol = si.si_proto;
|
||||
|
||||
if (svcport_str == NULL) {
|
||||
svcport_str = malloc(NI_MAXSERV * sizeof(char));
|
||||
if (svcport_str == NULL)
|
||||
out_of_mem();
|
||||
|
||||
if (getnameinfo(res->ai_addr,
|
||||
res->ai_addr->sa_len, NULL, NI_MAXHOST,
|
||||
svcport_str, NI_MAXSERV * sizeof(char),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV))
|
||||
errx(1, "Cannot get port number");
|
||||
}
|
||||
|
||||
if((aicode = getaddrinfo(NULL, svcport_str, &hints,
|
||||
if ((aicode = getaddrinfo(NULL, port_str, &hints,
|
||||
&res)) != 0) {
|
||||
syslog(LOG_ERR, "cannot get local address: %s",
|
||||
gai_strerror(aicode));
|
||||
@ -728,6 +894,23 @@ create_service(struct netconfig *nconf)
|
||||
} /* end while */
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear out sockets after a failure to bind one of them, so that the
|
||||
* cycle of socket creation/binding can start anew.
|
||||
*/
|
||||
static void
|
||||
clearout_service(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sock_fdcnt; i++) {
|
||||
if (sock_fd[i] >= 0) {
|
||||
shutdown(sock_fd[i], SHUT_RDWR);
|
||||
close(sock_fd[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
@ -74,6 +74,8 @@ __RCSID("$NetBSD: lockd.c,v 1.7 2000/08/12 18:08:44 thorpej Exp $");
|
||||
#include "lockd.h"
|
||||
#include <rpcsvc/nlm_prot.h>
|
||||
|
||||
#define GETPORT_MAXTRY 20 /* Max tries to get a port # */
|
||||
|
||||
int debug_level = 0; /* 0 = no debugging syslog() calls */
|
||||
int _rpcsvcdirty = 0;
|
||||
|
||||
@ -84,13 +86,19 @@ int kernel_lockd_client;
|
||||
pid_t client_pid;
|
||||
struct mon mon_host;
|
||||
char **hosts, *svcport_str = NULL;
|
||||
static int mallocd_svcport = 0;
|
||||
static int *sock_fd;
|
||||
static int sock_fdcnt;
|
||||
static int sock_fdpos;
|
||||
int nhosts = 0;
|
||||
int xcreated = 0;
|
||||
char **addrs; /* actually (netid, uaddr) pairs */
|
||||
int naddrs; /* count of how many (netid, uaddr) pairs */
|
||||
char localhost[] = "localhost";
|
||||
|
||||
void create_service(struct netconfig *nconf);
|
||||
static int create_service(struct netconfig *nconf);
|
||||
static void complete_service(struct netconfig *nconf, char *port_str);
|
||||
static void clearout_service(void);
|
||||
void lookup_addresses(struct netconfig *nconf);
|
||||
void init_nsm(void);
|
||||
void nlm_prog_0(struct svc_req *, SVCXPRT *);
|
||||
@ -119,6 +127,8 @@ main(int argc, char **argv)
|
||||
int have_v6 = 1;
|
||||
int maxrec = RPC_MAXDATASIZE;
|
||||
in_port_t svcport = 0;
|
||||
int attempt_cnt, port_len, port_pos, ret;
|
||||
char **port_list;
|
||||
|
||||
while ((ch = getopt(argc, argv, "d:g:h:p:")) != (-1)) {
|
||||
switch (ch) {
|
||||
@ -309,6 +319,11 @@ main(int argc, char **argv)
|
||||
}
|
||||
endnetconfig(nc_handle);
|
||||
} else {
|
||||
attempt_cnt = 1;
|
||||
sock_fdcnt = 0;
|
||||
sock_fd = NULL;
|
||||
port_list = NULL;
|
||||
port_len = 0;
|
||||
nc_handle = setnetconfig();
|
||||
while ((nconf = getnetconfig(nc_handle))) {
|
||||
/* We want to listen only on udp6, tcp6, udp, tcp transports */
|
||||
@ -317,11 +332,96 @@ main(int argc, char **argv)
|
||||
if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
|
||||
/* DO NOTHING */
|
||||
} else {
|
||||
create_service(nconf);
|
||||
ret = create_service(nconf);
|
||||
if (ret == 1)
|
||||
/* Ignore this call */
|
||||
continue;
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* Failed to bind port, so close
|
||||
* off all sockets created and
|
||||
* try again if the port# was
|
||||
* dynamically assigned via
|
||||
* bind(2).
|
||||
*/
|
||||
clearout_service();
|
||||
if (mallocd_svcport != 0 &&
|
||||
attempt_cnt <
|
||||
GETPORT_MAXTRY) {
|
||||
free(svcport_str);
|
||||
svcport_str = NULL;
|
||||
mallocd_svcport = 0;
|
||||
} else {
|
||||
errno = EADDRINUSE;
|
||||
syslog(LOG_ERR,
|
||||
"bindresvport_sa: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start over at the first
|
||||
* service.
|
||||
*/
|
||||
free(sock_fd);
|
||||
sock_fdcnt = 0;
|
||||
sock_fd = NULL;
|
||||
nc_handle = setnetconfig();
|
||||
attempt_cnt++;
|
||||
} else if (mallocd_svcport != 0 &&
|
||||
attempt_cnt == GETPORT_MAXTRY) {
|
||||
/*
|
||||
* For the last attempt, allow
|
||||
* different port #s for each
|
||||
* nconf by saving the
|
||||
* svcport_str and setting it
|
||||
* back to NULL.
|
||||
*/
|
||||
port_list = realloc(port_list,
|
||||
(port_len + 1) *
|
||||
sizeof(char *));
|
||||
if (port_list == NULL)
|
||||
out_of_mem();
|
||||
port_list[port_len++] =
|
||||
svcport_str;
|
||||
svcport_str = NULL;
|
||||
mallocd_svcport = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Successfully bound the ports, so call complete_service() to
|
||||
* do the rest of the setup on the service(s).
|
||||
*/
|
||||
sock_fdpos = 0;
|
||||
port_pos = 0;
|
||||
nc_handle = setnetconfig();
|
||||
while ((nconf = getnetconfig(nc_handle))) {
|
||||
/* We want to listen only on udp6, tcp6, udp, tcp transports */
|
||||
if (nconf->nc_flag & NC_VISIBLE) {
|
||||
/* Skip if there's no IPv6 support */
|
||||
if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
|
||||
/* DO NOTHING */
|
||||
} else if (port_list != NULL) {
|
||||
if (port_pos >= port_len) {
|
||||
syslog(LOG_ERR,
|
||||
"too many port#s");
|
||||
exit(1);
|
||||
}
|
||||
complete_service(nconf,
|
||||
port_list[port_pos++]);
|
||||
} else
|
||||
complete_service(nconf, svcport_str);
|
||||
}
|
||||
}
|
||||
endnetconfig(nc_handle);
|
||||
free(sock_fd);
|
||||
if (port_list != NULL) {
|
||||
for (port_pos = 0; port_pos < port_len; port_pos++)
|
||||
free(port_list[port_pos]);
|
||||
free(port_list);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -386,29 +486,30 @@ main(int argc, char **argv)
|
||||
|
||||
/*
|
||||
* This routine creates and binds sockets on the appropriate
|
||||
* addresses. It gets called one time for each transport and
|
||||
* registrates the service with rpcbind on that trasport.
|
||||
* addresses. It gets called one time for each transport.
|
||||
* It returns 0 upon success, 1 for ingore the call and -1 to indicate
|
||||
* bind failed with EADDRINUSE.
|
||||
* Any file descriptors that have been created are stored in sock_fd and
|
||||
* the total count of them is maintained in sock_fdcnt.
|
||||
*/
|
||||
void
|
||||
static int
|
||||
create_service(struct netconfig *nconf)
|
||||
{
|
||||
struct addrinfo hints, *res = NULL;
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr_in6 *sin6;
|
||||
struct __rpc_sockinfo si;
|
||||
struct netbuf servaddr;
|
||||
SVCXPRT *transp = NULL;
|
||||
int aicode;
|
||||
int fd;
|
||||
int nhostsbak;
|
||||
int r;
|
||||
int registered = 0;
|
||||
u_int32_t host_addr[4]; /* IPv4 or IPv6 */
|
||||
int mallocd_res;
|
||||
|
||||
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS_ORD))
|
||||
return; /* not my type */
|
||||
return (1); /* not my type */
|
||||
|
||||
/*
|
||||
* XXX - using RPC library internal functions.
|
||||
@ -416,7 +517,7 @@ create_service(struct netconfig *nconf)
|
||||
if (!__rpc_nconf2sockinfo(nconf, &si)) {
|
||||
syslog(LOG_ERR, "cannot get information for %s",
|
||||
nconf->nc_netid);
|
||||
return;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Get rpc.statd's address on this transport */
|
||||
@ -432,6 +533,11 @@ create_service(struct netconfig *nconf)
|
||||
nhostsbak = nhosts;
|
||||
while (nhostsbak > 0) {
|
||||
--nhostsbak;
|
||||
sock_fd = realloc(sock_fd, (sock_fdcnt + 1) * sizeof(int));
|
||||
if (sock_fd == NULL)
|
||||
out_of_mem();
|
||||
sock_fd[sock_fdcnt++] = -1; /* Set invalid for now. */
|
||||
mallocd_res = 0;
|
||||
|
||||
/*
|
||||
* XXX - using RPC library internal functions.
|
||||
@ -446,7 +552,7 @@ create_service(struct netconfig *nconf)
|
||||
case AF_INET:
|
||||
if (inet_pton(AF_INET, hosts[nhostsbak],
|
||||
host_addr) == 1) {
|
||||
hints.ai_flags &= AI_NUMERICHOST;
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
} else {
|
||||
/*
|
||||
* Skip if we have an AF_INET6 address.
|
||||
@ -461,7 +567,7 @@ create_service(struct netconfig *nconf)
|
||||
case AF_INET6:
|
||||
if (inet_pton(AF_INET6, hosts[nhostsbak],
|
||||
host_addr) == 1) {
|
||||
hints.ai_flags &= AI_NUMERICHOST;
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
} else {
|
||||
/*
|
||||
* Skip if we have an AF_INET address.
|
||||
@ -485,6 +591,7 @@ create_service(struct netconfig *nconf)
|
||||
res = malloc(sizeof(struct addrinfo));
|
||||
if (res == NULL)
|
||||
out_of_mem();
|
||||
mallocd_res = 1;
|
||||
res->ai_flags = hints.ai_flags;
|
||||
res->ai_family = hints.ai_family;
|
||||
res->ai_protocol = hints.ai_protocol;
|
||||
@ -498,7 +605,7 @@ create_service(struct netconfig *nconf)
|
||||
sin->sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
res->ai_addr = (struct sockaddr*) sin;
|
||||
res->ai_addrlen = (socklen_t)
|
||||
sizeof(res->ai_addr);
|
||||
sizeof(struct sockaddr_in);
|
||||
break;
|
||||
case AF_INET6:
|
||||
sin6 = malloc(sizeof(struct sockaddr_in6));
|
||||
@ -508,10 +615,14 @@ create_service(struct netconfig *nconf)
|
||||
sin6->sin6_port = htons(0);
|
||||
sin6->sin6_addr = in6addr_any;
|
||||
res->ai_addr = (struct sockaddr*) sin6;
|
||||
res->ai_addrlen = (socklen_t) sizeof(res->ai_addr);
|
||||
res->ai_addrlen = (socklen_t)
|
||||
sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
syslog(LOG_ERR,
|
||||
"bad addr fam %d",
|
||||
res->ai_family);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if ((aicode = getaddrinfo(NULL, svcport_str,
|
||||
@ -520,6 +631,7 @@ create_service(struct netconfig *nconf)
|
||||
"cannot get local address for %s: %s",
|
||||
nconf->nc_netid,
|
||||
gai_strerror(aicode));
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -529,16 +641,92 @@ create_service(struct netconfig *nconf)
|
||||
syslog(LOG_ERR,
|
||||
"cannot get local address for %s: %s",
|
||||
nconf->nc_netid, gai_strerror(aicode));
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Store the fd. */
|
||||
sock_fd[sock_fdcnt - 1] = fd;
|
||||
|
||||
/* Now, attempt the bind. */
|
||||
r = bindresvport_sa(fd, res->ai_addr);
|
||||
if (r != 0) {
|
||||
if (errno == EADDRINUSE && mallocd_svcport != 0) {
|
||||
if (mallocd_res != 0) {
|
||||
free(res->ai_addr);
|
||||
free(res);
|
||||
} else
|
||||
freeaddrinfo(res);
|
||||
return (-1);
|
||||
}
|
||||
syslog(LOG_ERR, "bindresvport_sa: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (svcport_str == NULL) {
|
||||
svcport_str = malloc(NI_MAXSERV * sizeof(char));
|
||||
if (svcport_str == NULL)
|
||||
out_of_mem();
|
||||
mallocd_svcport = 1;
|
||||
|
||||
if (getnameinfo(res->ai_addr,
|
||||
res->ai_addr->sa_len, NULL, NI_MAXHOST,
|
||||
svcport_str, NI_MAXSERV * sizeof(char),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV))
|
||||
errx(1, "Cannot get port number");
|
||||
}
|
||||
if (mallocd_res != 0) {
|
||||
free(res->ai_addr);
|
||||
free(res);
|
||||
} else
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after all the create_service() calls have succeeded, to complete
|
||||
* the setup and registration.
|
||||
*/
|
||||
static void
|
||||
complete_service(struct netconfig *nconf, char *port_str)
|
||||
{
|
||||
struct addrinfo hints, *res = NULL;
|
||||
struct __rpc_sockinfo si;
|
||||
struct netbuf servaddr;
|
||||
SVCXPRT *transp = NULL;
|
||||
int aicode, fd, nhostsbak;
|
||||
int registered = 0;
|
||||
|
||||
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS_ORD))
|
||||
return; /* not my type */
|
||||
|
||||
/*
|
||||
* XXX - using RPC library internal functions.
|
||||
*/
|
||||
if (!__rpc_nconf2sockinfo(nconf, &si)) {
|
||||
syslog(LOG_ERR, "cannot get information for %s",
|
||||
nconf->nc_netid);
|
||||
return;
|
||||
}
|
||||
|
||||
nhostsbak = nhosts;
|
||||
while (nhostsbak > 0) {
|
||||
--nhostsbak;
|
||||
if (sock_fdpos >= sock_fdcnt) {
|
||||
/* Should never happen. */
|
||||
syslog(LOG_ERR, "Ran out of socket fd's");
|
||||
return;
|
||||
}
|
||||
fd = sock_fd[sock_fdpos++];
|
||||
if (fd < 0)
|
||||
continue;
|
||||
|
||||
if (nconf->nc_semantics != NC_TPI_CLTS)
|
||||
listen(fd, SOMAXCONN);
|
||||
|
||||
@ -582,19 +770,7 @@ create_service(struct netconfig *nconf)
|
||||
hints.ai_socktype = si.si_socktype;
|
||||
hints.ai_protocol = si.si_proto;
|
||||
|
||||
if (svcport_str == NULL) {
|
||||
svcport_str = malloc(NI_MAXSERV * sizeof(char));
|
||||
if (svcport_str == NULL)
|
||||
out_of_mem();
|
||||
|
||||
if (getnameinfo(res->ai_addr,
|
||||
res->ai_addr->sa_len, NULL, NI_MAXHOST,
|
||||
svcport_str, NI_MAXSERV * sizeof(char),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV))
|
||||
errx(1, "Cannot get port number");
|
||||
}
|
||||
|
||||
if((aicode = getaddrinfo(NULL, svcport_str, &hints,
|
||||
if ((aicode = getaddrinfo(NULL, port_str, &hints,
|
||||
&res)) != 0) {
|
||||
syslog(LOG_ERR, "cannot get local address: %s",
|
||||
gai_strerror(aicode));
|
||||
@ -616,6 +792,23 @@ create_service(struct netconfig *nconf)
|
||||
} /* end while */
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear out sockets after a failure to bind one of them, so that the
|
||||
* cycle of socket creation/binding can start anew.
|
||||
*/
|
||||
static void
|
||||
clearout_service(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sock_fdcnt; i++) {
|
||||
if (sock_fd[i] >= 0) {
|
||||
shutdown(sock_fd[i], SHUT_RDWR);
|
||||
close(sock_fd[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up addresses for the kernel to create transports for.
|
||||
*/
|
||||
|
@ -39,6 +39,7 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <rpc/rpc.h>
|
||||
@ -55,13 +56,21 @@ __FBSDID("$FreeBSD$");
|
||||
#include <unistd.h>
|
||||
#include "statd.h"
|
||||
|
||||
#define GETPORT_MAXTRY 20 /* Max tries to get a port # */
|
||||
|
||||
int debug = 0; /* Controls syslog() calls for debug messages */
|
||||
|
||||
char **hosts, *svcport_str = NULL;
|
||||
int nhosts = 0;
|
||||
int xcreated = 0;
|
||||
static int mallocd_svcport = 0;
|
||||
static int *sock_fd;
|
||||
static int sock_fdcnt;
|
||||
static int sock_fdpos;
|
||||
|
||||
void create_service(struct netconfig *nconf);
|
||||
static int create_service(struct netconfig *nconf);
|
||||
static void complete_service(struct netconfig *nconf, char *port_str);
|
||||
static void clearout_service(void);
|
||||
static void handle_sigchld(int sig);
|
||||
void out_of_mem(void);
|
||||
|
||||
@ -78,6 +87,8 @@ main(int argc, char **argv)
|
||||
char *endptr, **hosts_bak;
|
||||
int have_v6 = 1;
|
||||
int maxrec = RPC_MAXDATASIZE;
|
||||
int attempt_cnt, port_len, port_pos, ret;
|
||||
char **port_list;
|
||||
|
||||
while ((ch = getopt(argc, argv, "dh:p:")) != -1)
|
||||
switch (ch) {
|
||||
@ -176,6 +187,11 @@ main(int argc, char **argv)
|
||||
hosts[nhosts - 1] = "127.0.0.1";
|
||||
}
|
||||
|
||||
attempt_cnt = 1;
|
||||
sock_fdcnt = 0;
|
||||
sock_fd = NULL;
|
||||
port_list = NULL;
|
||||
port_len = 0;
|
||||
nc_handle = setnetconfig();
|
||||
while ((nconf = getnetconfig(nc_handle))) {
|
||||
/* We want to listen only on udp6, tcp6, udp, tcp transports */
|
||||
@ -184,11 +200,87 @@ main(int argc, char **argv)
|
||||
if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
|
||||
/* DO NOTHING */
|
||||
} else {
|
||||
create_service(nconf);
|
||||
ret = create_service(nconf);
|
||||
if (ret == 1)
|
||||
/* Ignore this call */
|
||||
continue;
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* Failed to bind port, so close off
|
||||
* all sockets created and try again
|
||||
* if the port# was dynamically
|
||||
* assigned via bind(2).
|
||||
*/
|
||||
clearout_service();
|
||||
if (mallocd_svcport != 0 &&
|
||||
attempt_cnt < GETPORT_MAXTRY) {
|
||||
free(svcport_str);
|
||||
svcport_str = NULL;
|
||||
mallocd_svcport = 0;
|
||||
} else {
|
||||
errno = EADDRINUSE;
|
||||
syslog(LOG_ERR,
|
||||
"bindresvport_sa: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Start over at the first service. */
|
||||
free(sock_fd);
|
||||
sock_fdcnt = 0;
|
||||
sock_fd = NULL;
|
||||
nc_handle = setnetconfig();
|
||||
attempt_cnt++;
|
||||
} else if (mallocd_svcport != 0 &&
|
||||
attempt_cnt == GETPORT_MAXTRY) {
|
||||
/*
|
||||
* For the last attempt, allow
|
||||
* different port #s for each nconf
|
||||
* by saving the svcport_str and
|
||||
* setting it back to NULL.
|
||||
*/
|
||||
port_list = realloc(port_list,
|
||||
(port_len + 1) * sizeof(char *));
|
||||
if (port_list == NULL)
|
||||
out_of_mem();
|
||||
port_list[port_len++] = svcport_str;
|
||||
svcport_str = NULL;
|
||||
mallocd_svcport = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Successfully bound the ports, so call complete_service() to
|
||||
* do the rest of the setup on the service(s).
|
||||
*/
|
||||
sock_fdpos = 0;
|
||||
port_pos = 0;
|
||||
nc_handle = setnetconfig();
|
||||
while ((nconf = getnetconfig(nc_handle))) {
|
||||
/* We want to listen only on udp6, tcp6, udp, tcp transports */
|
||||
if (nconf->nc_flag & NC_VISIBLE) {
|
||||
/* Skip if there's no IPv6 support */
|
||||
if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
|
||||
/* DO NOTHING */
|
||||
} else if (port_list != NULL) {
|
||||
if (port_pos >= port_len) {
|
||||
syslog(LOG_ERR, "too many port#s");
|
||||
exit(1);
|
||||
}
|
||||
complete_service(nconf, port_list[port_pos++]);
|
||||
} else
|
||||
complete_service(nconf, svcport_str);
|
||||
}
|
||||
}
|
||||
endnetconfig(nc_handle);
|
||||
free(sock_fd);
|
||||
if (port_list != NULL) {
|
||||
for (port_pos = 0; port_pos < port_len; port_pos++)
|
||||
free(port_list[port_pos]);
|
||||
free(port_list);
|
||||
}
|
||||
|
||||
init_file("/var/db/statd.status");
|
||||
|
||||
/* Note that it is NOT sensible to run this program from inetd - the */
|
||||
@ -215,29 +307,30 @@ main(int argc, char **argv)
|
||||
|
||||
/*
|
||||
* This routine creates and binds sockets on the appropriate
|
||||
* addresses. It gets called one time for each transport and
|
||||
* registrates the service with rpcbind on that trasport.
|
||||
* addresses. It gets called one time for each transport.
|
||||
* It returns 0 upon success, 1 for ingore the call and -1 to indicate
|
||||
* bind failed with EADDRINUSE.
|
||||
* Any file descriptors that have been created are stored in sock_fd and
|
||||
* the total count of them is maintained in sock_fdcnt.
|
||||
*/
|
||||
void
|
||||
static int
|
||||
create_service(struct netconfig *nconf)
|
||||
{
|
||||
struct addrinfo hints, *res = NULL;
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr_in6 *sin6;
|
||||
struct __rpc_sockinfo si;
|
||||
struct netbuf servaddr;
|
||||
SVCXPRT *transp = NULL;
|
||||
int aicode;
|
||||
int fd;
|
||||
int nhostsbak;
|
||||
int r;
|
||||
int registered = 0;
|
||||
u_int32_t host_addr[4]; /* IPv4 or IPv6 */
|
||||
int mallocd_res;
|
||||
|
||||
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS_ORD))
|
||||
return; /* not my type */
|
||||
return (1); /* not my type */
|
||||
|
||||
/*
|
||||
* XXX - using RPC library internal functions.
|
||||
@ -245,7 +338,7 @@ create_service(struct netconfig *nconf)
|
||||
if (!__rpc_nconf2sockinfo(nconf, &si)) {
|
||||
syslog(LOG_ERR, "cannot get information for %s",
|
||||
nconf->nc_netid);
|
||||
return;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Get rpc.statd's address on this transport */
|
||||
@ -261,6 +354,11 @@ create_service(struct netconfig *nconf)
|
||||
nhostsbak = nhosts;
|
||||
while (nhostsbak > 0) {
|
||||
--nhostsbak;
|
||||
sock_fd = realloc(sock_fd, (sock_fdcnt + 1) * sizeof(int));
|
||||
if (sock_fd == NULL)
|
||||
out_of_mem();
|
||||
sock_fd[sock_fdcnt++] = -1; /* Set invalid for now. */
|
||||
mallocd_res = 0;
|
||||
|
||||
/*
|
||||
* XXX - using RPC library internal functions.
|
||||
@ -274,7 +372,7 @@ create_service(struct netconfig *nconf)
|
||||
case AF_INET:
|
||||
if (inet_pton(AF_INET, hosts[nhostsbak],
|
||||
host_addr) == 1) {
|
||||
hints.ai_flags &= AI_NUMERICHOST;
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
} else {
|
||||
/*
|
||||
* Skip if we have an AF_INET6 address.
|
||||
@ -289,7 +387,7 @@ create_service(struct netconfig *nconf)
|
||||
case AF_INET6:
|
||||
if (inet_pton(AF_INET6, hosts[nhostsbak],
|
||||
host_addr) == 1) {
|
||||
hints.ai_flags &= AI_NUMERICHOST;
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
} else {
|
||||
/*
|
||||
* Skip if we have an AF_INET address.
|
||||
@ -313,6 +411,7 @@ create_service(struct netconfig *nconf)
|
||||
res = malloc(sizeof(struct addrinfo));
|
||||
if (res == NULL)
|
||||
out_of_mem();
|
||||
mallocd_res = 1;
|
||||
res->ai_flags = hints.ai_flags;
|
||||
res->ai_family = hints.ai_family;
|
||||
res->ai_protocol = hints.ai_protocol;
|
||||
@ -326,7 +425,7 @@ create_service(struct netconfig *nconf)
|
||||
sin->sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
res->ai_addr = (struct sockaddr*) sin;
|
||||
res->ai_addrlen = (socklen_t)
|
||||
sizeof(res->ai_addr);
|
||||
sizeof(struct sockaddr_in);
|
||||
break;
|
||||
case AF_INET6:
|
||||
sin6 = malloc(sizeof(struct sockaddr_in6));
|
||||
@ -336,10 +435,13 @@ create_service(struct netconfig *nconf)
|
||||
sin6->sin6_port = htons(0);
|
||||
sin6->sin6_addr = in6addr_any;
|
||||
res->ai_addr = (struct sockaddr*) sin6;
|
||||
res->ai_addrlen = (socklen_t) sizeof(res->ai_addr);
|
||||
res->ai_addrlen = (socklen_t)
|
||||
sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
syslog(LOG_ERR, "bad addr fam %d",
|
||||
res->ai_family);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if ((aicode = getaddrinfo(NULL, svcport_str,
|
||||
@ -348,6 +450,7 @@ create_service(struct netconfig *nconf)
|
||||
"cannot get local address for %s: %s",
|
||||
nconf->nc_netid,
|
||||
gai_strerror(aicode));
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -357,16 +460,91 @@ create_service(struct netconfig *nconf)
|
||||
syslog(LOG_ERR,
|
||||
"cannot get local address for %s: %s",
|
||||
nconf->nc_netid, gai_strerror(aicode));
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the fd. */
|
||||
sock_fd[sock_fdcnt - 1] = fd;
|
||||
|
||||
/* Now, attempt the bind. */
|
||||
r = bindresvport_sa(fd, res->ai_addr);
|
||||
if (r != 0) {
|
||||
if (errno == EADDRINUSE && mallocd_svcport != 0) {
|
||||
if (mallocd_res != 0) {
|
||||
free(res->ai_addr);
|
||||
free(res);
|
||||
} else
|
||||
freeaddrinfo(res);
|
||||
return (-1);
|
||||
}
|
||||
syslog(LOG_ERR, "bindresvport_sa: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (svcport_str == NULL) {
|
||||
svcport_str = malloc(NI_MAXSERV * sizeof(char));
|
||||
if (svcport_str == NULL)
|
||||
out_of_mem();
|
||||
mallocd_svcport = 1;
|
||||
|
||||
if (getnameinfo(res->ai_addr,
|
||||
res->ai_addr->sa_len, NULL, NI_MAXHOST,
|
||||
svcport_str, NI_MAXSERV * sizeof(char),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV))
|
||||
errx(1, "Cannot get port number");
|
||||
}
|
||||
if (mallocd_res != 0) {
|
||||
free(res->ai_addr);
|
||||
free(res);
|
||||
} else
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after all the create_service() calls have succeeded, to complete
|
||||
* the setup and registration.
|
||||
*/
|
||||
static void
|
||||
complete_service(struct netconfig *nconf, char *port_str)
|
||||
{
|
||||
struct addrinfo hints, *res = NULL;
|
||||
struct __rpc_sockinfo si;
|
||||
struct netbuf servaddr;
|
||||
SVCXPRT *transp = NULL;
|
||||
int aicode, fd, nhostsbak;
|
||||
int registered = 0;
|
||||
|
||||
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS_ORD))
|
||||
return; /* not my type */
|
||||
|
||||
/*
|
||||
* XXX - using RPC library internal functions.
|
||||
*/
|
||||
if (!__rpc_nconf2sockinfo(nconf, &si)) {
|
||||
syslog(LOG_ERR, "cannot get information for %s",
|
||||
nconf->nc_netid);
|
||||
return;
|
||||
}
|
||||
|
||||
nhostsbak = nhosts;
|
||||
while (nhostsbak > 0) {
|
||||
--nhostsbak;
|
||||
if (sock_fdpos >= sock_fdcnt) {
|
||||
/* Should never happen. */
|
||||
syslog(LOG_ERR, "Ran out of socket fd's");
|
||||
return;
|
||||
}
|
||||
fd = sock_fd[sock_fdpos++];
|
||||
if (fd < 0)
|
||||
continue;
|
||||
|
||||
if (nconf->nc_semantics != NC_TPI_CLTS)
|
||||
listen(fd, SOMAXCONN);
|
||||
|
||||
@ -397,19 +575,8 @@ create_service(struct netconfig *nconf)
|
||||
hints.ai_socktype = si.si_socktype;
|
||||
hints.ai_protocol = si.si_proto;
|
||||
|
||||
if (svcport_str == NULL) {
|
||||
svcport_str = malloc(NI_MAXSERV * sizeof(char));
|
||||
if (svcport_str == NULL)
|
||||
out_of_mem();
|
||||
|
||||
if (getnameinfo(res->ai_addr,
|
||||
res->ai_addr->sa_len, NULL, NI_MAXHOST,
|
||||
svcport_str, NI_MAXSERV * sizeof(char),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV))
|
||||
errx(1, "Cannot get port number");
|
||||
}
|
||||
|
||||
if((aicode = getaddrinfo(NULL, svcport_str, &hints,
|
||||
if ((aicode = getaddrinfo(NULL, port_str, &hints,
|
||||
&res)) != 0) {
|
||||
syslog(LOG_ERR, "cannot get local address: %s",
|
||||
gai_strerror(aicode));
|
||||
@ -428,6 +595,23 @@ create_service(struct netconfig *nconf)
|
||||
} /* end while */
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear out sockets after a failure to bind one of them, so that the
|
||||
* cycle of socket creation/binding can start anew.
|
||||
*/
|
||||
static void
|
||||
clearout_service(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sock_fdcnt; i++) {
|
||||
if (sock_fd[i] >= 0) {
|
||||
shutdown(sock_fd[i], SHUT_RDWR);
|
||||
close(sock_fd[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user