This commit is contained in:
Attilio Rao 2011-06-03 17:09:15 +00:00
commit d7073a2b3b
45 changed files with 1813 additions and 507 deletions

View File

@ -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.

View File

@ -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) {

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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,

View File

@ -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)
{

View File

@ -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) */

View File

@ -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,

View File

@ -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;

View File

@ -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)

View File

@ -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",

View File

@ -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);

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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:

View File

@ -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()
*

View File

@ -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

View File

@ -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, &regions, &regions_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;

View File

@ -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, &regions, &regions_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();

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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:

View 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_ */

View File

@ -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)

View File

@ -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 {

View File

@ -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
View 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
View 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
View 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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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}

View File

@ -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)
{

View File

@ -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.
*/

View File

@ -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()
{