Compare commits

...

257 Commits

Author SHA1 Message Date
cd30bedd2b system: some user inmprovements
* not use cgo
* add lock/unlock user

Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru>
2015-11-25 11:26:00 +00:00
Jonathan Boulle
fa0178cd47 Merge pull request #400 from sethp/coreos-cloudinit/gzip-magic
gzip autodetection
2015-11-11 13:49:14 -08:00
Seth Pellegrino
778a47b957 userdata: gzip autodetection
look for the gzip magic number at the beginning of a data source, and,
if found, decompress the input before further processing.

Addresses coreos/bugs#741.
2015-11-11 08:21:00 -08:00
Seth Pellegrino
86909e5bcb test: added coreos-cloudinit_test to test script
Include the root project directory in packages
to be built/tested.
2015-11-11 08:06:36 -08:00
Josh Wood
0fd3cd2fae Merge pull request #406 from joshix/doubledash0
Vmware-guestinfo: Double hyphen long options.
2015-11-10 10:21:06 -08:00
Josh Wood
ad81cf7f78 Vmware-guestinfo: Double hyphen long options.
In line with https://github.com/coreos/docs/issues/650,
revert a little bit of https://github.com/coreos/coreos-cloudinit/pull/404
to document `--longoption` with two hyphens in document and Usage.
2015-11-09 16:31:30 -08:00
Josh Wood
0a500a19ff Merge pull request #405 from omkensey/doc-link-blob-fix
docs: fix links to specific blobs
2015-11-08 23:54:34 -08:00
Joe Thompson
b9f34d93ad docs: fix links to specific blobs
Rather than link to specific blob hashes, now that things have been synced to 0.4.9 we can link to the 0.4 release for original etcd; also fixes a link that was to a blob hash of configuration.md instead of the head of master for etcd.
2015-11-09 02:05:37 -05:00
Josh Wood
2f5d8cc188 Merge pull request #404 from joshix/backdoorname
Docs/vmware-backdoor: Rename backdoor to guestinfo
2015-11-05 15:35:45 -08:00
Josh Wood
b56c0f5609 Docs/vmware-backdoor: Rename backdoor to guestinfo
Based on results of google searches on a few possible titles
to improve on the connotation of backdoor, Guestinfo Configuration
Interface (as part of the RPC API) seems recognizable in vmware
circles. Friends call it just guestinfo.

This changeset also makes docs and usage for this flag appear with
a single hypen (-flag) like most go programs do.
2015-11-05 15:27:33 -08:00
Alex Crawford
cd1994b007 Merge pull request #403 from mdlayher/digitalocean_anchor_gateway
network: do not assign gateway for DigitalOcean anchor IP address
2015-10-27 09:10:34 -07:00
Matt Layher
1fd780befc network: do not assign gateway for DigitalOcean anchor IP address 2015-10-27 10:49:05 -04:00
Rob Szumski
8847a471c5 Merge pull request #393 from endocode/kayrus/vmware
Updated vmware info / Fixed help help message
2015-10-21 09:20:59 -07:00
kayrus
c0c144bd56 Added additional vmware info, fixed cli help 2015-10-19 10:33:27 +02:00
Alex Crawford
1d962916b9 Merge pull request #402 from xiang90/etcd2_wal
config: add wal_dir into etcd2.go
2015-10-15 12:29:49 -07:00
Xiang Li
bda6668f00 config: add wal_dir into etcd2.go 2015-10-15 09:36:48 -07:00
Alex Crawford
0f828db9a3 Merge pull request #401 from mischief/update-fleet-options
config: sync fleet options
2015-10-14 11:05:17 -07:00
Nick Owens
5970000589 config: sync fleet options 2015-10-14 11:02:59 -07:00
Alex Crawford
7870fa8c9d Merge pull request #399 from mdlayher/digitalocean_floatingip
datasource, network: add support for DigitalOcean floating IPs
2015-10-13 11:59:46 -07:00
Matt Layher
b4d45306b2 datasource, network: add support for DigitalOcean floating IPs 2015-10-09 10:52:05 -04:00
Michael Marineau
3c2b5e6636 Merge pull request #398 from marineam/gomax
main: default to GOMAXPROCS=1
2015-09-30 20:43:03 -07:00
Michael Marineau
bf743b3060 main: default to GOMAXPROCS=1 2015-09-30 17:23:40 -07:00
Jonathan Boulle
3b98be7788 Merge pull request #396 from crawford/bugs
readme: add link to coreos/bugs
2015-09-24 19:44:48 -07:00
Alex Crawford
746685023f readme: add link to coreos/bugs 2015-09-24 17:50:06 -07:00
Alex Crawford
a0fcbb16d6 Merge pull request #395 from crawford/locksmith
config: add group and window options for locksmith
2015-09-23 23:21:19 -07:00
Alex Crawford
f63fa39a2d config: format license 2015-09-23 23:19:47 -07:00
Alex Crawford
0ae90f3b22 config: add group and window options for locksmith
The regular expression for RebootWindowLength comes from
https://golang.org/pkg/time/#ParseDuration.
2015-09-23 23:19:41 -07:00
Alex Crawford
dee67b964a Merge pull request #385 from endocode/kayrus/fleet
doc: added coreos-cloudinit options description
2015-09-21 10:32:20 -07:00
Michael Marineau
05062188f1 Merge pull request #391 from marineam/go-1.5.1
Fix and enable testing on Go 1.5
2015-09-16 17:34:43 -07:00
Michael Marineau
5405fc9d0d network: update error check for Go 1.5
Changed upstream:
055ecb7be5
2015-09-16 13:26:21 -07:00
Michael Marineau
c7f327bb89 travis: enable go 1.5 2015-09-16 13:02:45 -07:00
Alex Crawford
71e2b2bddb Merge pull request #389 from stresler/patch-1
cloudinit: Removing convert-netconf from Packet OEM
2015-09-11 09:13:10 -07:00
stresler
8fac253214 Removing convert-netconf from packet OEM
We still utilize the network code on first boot, so it should remain until we implement ignition, but we don't want it on subsequent boots, which is what this line would do.
2015-09-11 12:00:10 -04:00
Alex Crawford
e19fd09664 Merge pull request #386 from crawford/quotes
docs: quote everything
2015-09-08 18:45:52 -07:00
Alex Crawford
4a25948b53 docs: quote everything
I realize this is one of the selling points of YAML, but it causes far
too much confusion. Turns out typing is a good thing.
2015-09-08 18:40:21 -07:00
kayrus
f5cc75299a doc: added coreos-cloudinit options description 2015-09-08 12:23:10 +02:00
Michael Marineau
f816819c6d Merge pull request #380 from endocode/kayrus/mod_cloudinit_locations
Filled cloud providers cloud-config URLs
2015-09-07 10:41:49 -07:00
Alex Crawford
5f688a0a21 Merge pull request #379 from endocode/kayrus/trim_fix
cloudinit: trim trailing whitespaces in #cloud-config header
2015-09-07 10:09:42 -07:00
kayrus
f92dcb7968 cloudinit: trim trailing whitespaces in #cloud-config header 2015-09-07 18:30:02 +02:00
Alex Crawford
bb71f5e072 Merge pull request #383 from sigma/t/feature/vmware-config-url
datasource/vmware: introduce guestinfo.coreos.config.url
2015-09-04 09:20:42 -07:00
Yann Hodique
ed512c1cac datasource/vmware: introduce guestinfo.coreos.config.url
allow use of a URL instead of an inline document.
Inline document takes precedence.
2015-09-03 20:50:19 -07:00
Alex Crawford
94f8e00054 Merge pull request #382 from sigma/t/fix/assertion
datasource/vmware: fix assertion
2015-09-03 18:39:22 -07:00
Yann Hodique
b5cb942acb datasource/vmware: fix assertion
we definitely don't always want nil
2015-09-03 18:15:23 -07:00
Rob Szumski
de38ac5c98 Merge pull request #381 from endocode/kayrus/new_docs
docs: added cloud-config headers explanation
2015-09-02 08:54:28 -07:00
kayrus
dfc5f2627f Added cloud-config headers explanation 2015-09-02 15:12:27 +02:00
Alex Crawford
057e8094d5 Merge pull request #345 from crawford/vmware
datasource: add vmware backdoor
2015-09-01 15:41:01 -07:00
Alex Crawford
15b50d4712 doc: Add docs for VMware backdoor 2015-09-01 15:36:36 -07:00
Alex Crawford
dda5032296 cloudinit: add vmware backdoor 2015-09-01 15:36:36 -07:00
Alex Crawford
d675638776 datasource: add vmware 2015-09-01 15:36:35 -07:00
kayrus
61e3595520 Added table for cloud-config locations 2015-08-31 12:04:23 +02:00
kayrus
4f76283917 Filled cloud providers cloud-config URLs 2015-08-28 12:58:00 +02:00
Rob Szumski
9c4aca6c9a Merge pull request #366 from endocode/master
docs: add cloud-config locations
2015-08-26 10:06:26 -04:00
Alex Crawford
13dc11abf3 godeps: add github.com/sigma/vmw-guestinfo 2015-08-24 09:03:29 -07:00
Alex Crawford
9ba25550a1 datasource: use opaque object instead of string
Rather than serializing the network config into a string and then later
deserializing it, just pass the object through directly.
2015-08-24 09:03:29 -07:00
Alex Crawford
81ffa056bd log: use log.Print instead of fmt.Print 2015-08-23 19:30:03 -07:00
kayrus
8c804a1124 Removed {{site.baseurl}} 2015-08-18 11:31:52 +02:00
kayrus
0a46b32c88 Updated cloudconfig docs
* Fixed openstack config-drive link
* Added cloud-config-locations.md
2015-08-17 16:53:33 +02:00
Alex Crawford
fac805dc11 Merge pull request #375 from crawford/build
build: extract the version number from git
2015-08-12 11:09:29 -07:00
Alex Crawford
94ea0b99ea Merge pull request #374 from crawford/timeout
pkg/http: up the timeout to 10 seconds
2015-08-12 11:08:04 -07:00
Alex Crawford
56a80d84cf build: extract the version number from git
Update the tests as well.
2015-08-12 11:05:04 -07:00
Alex Crawford
00c9174da4 pkg/http: up the timeout to 10 seconds
Additionally, fix the units on that multiplication. This isn't
acceleration.
2015-08-11 10:42:41 -07:00
Alex Crawford
ec8742c9ba Merge pull request #371 from crawford/http-client
pkg: update HttpClient to use newer Go features
2015-08-07 20:03:01 -07:00
Alex Crawford
b3b09aeb19 pkg: update HttpClient to use newer Go features 2015-08-07 19:30:47 -07:00
Alex Crawford
481d98c0b5 Merge pull request #370 from crawford/etcd2
config: update flags for etcd 2.1
2015-08-07 17:03:43 -07:00
Alex Crawford
f30727a675 config: update flags for etcd 2.1 2015-08-07 16:20:36 -07:00
kayrus
fc4efb086b Merge https://github.com/coreos/coreos-cloudinit 2015-07-28 14:40:18 +02:00
kayrus
5383bd1f07 Fixed Cloud-Config examples 2015-07-27 18:29:21 +02:00
Alex Crawford
e1305937e6 Merge pull request #362 from bodgit/mkisofs
Add note for creating config-drive ISO on OS X
2015-07-23 18:42:37 -07:00
Alex Crawford
20c4653ecf Merge pull request #365 from cusspvz/flannel/add-public-ip-opt
Add PublicIP option on flannel
2015-07-23 13:41:06 -07:00
José Moreira
43c6da06a5 add public_ip opt on cloud-config.md 2015-07-23 17:04:37 +01:00
José Moreira
7ab84601c3 Add PublicIP opt 2015-07-22 22:54:03 +01:00
Alex Crawford
a24b23663c Merge pull request #364 from crawford/etcd
config: specific valid values for ETCD_PROXY
2015-07-21 22:21:25 -07:00
Alex Crawford
91fe744bd2 config: specific valid values for ETCD_PROXY 2015-07-21 14:20:10 -07:00
Matt Dainty
eb8fc045ee Add note for creating config-drive ISO on OS X 2015-07-20 10:27:02 +01:00
Alex Crawford
ba83b2871f coreos-cloudinit: bump to v1.5.0+git 2015-07-14 11:55:39 -07:00
Alex Crawford
f36821f7ce coreos-cloudinit: bump to v1.5.0 2015-07-14 11:54:56 -07:00
Alex Crawford
97fe210760 Merge pull request #356 from crawford/ignition
config: recognize Ignition configs and no-op
2015-07-10 16:34:18 -07:00
Alex Crawford
c6400f7751 config: recognize Ignition configs and no-op 2015-07-10 16:32:57 -07:00
Alex Crawford
f6647634f0 Merge pull request #352 from packethost/packet-datasource
datasource: add packethost metadata
2015-07-10 12:25:37 -07:00
Sam Tresler
837d3d3622 datasource: add packethost metadata 2015-07-10 15:13:57 -04:00
Alex Crawford
1063a4b9ee Merge pull request #351 from packethost/bond-config-options
Bond options persisted to the generated netdev file.
2015-07-10 09:08:31 -07:00
Sam Tresler
081f77a102 Persisting bond options to the netdev file, and updating the test. 2015-06-23 11:21:26 -04:00
Alex Crawford
41289286ca Merge pull request #354 from packethost/go-ci-versions
Go ci versions
2015-06-22 16:04:56 -07:00
Sam Tresler
d50a4069a6 Removing goland 1.3 and 1.2 from Travis testing 2015-06-22 18:43:27 -04:00
Alex Crawford
be0c9c56e4 Merge pull request #347 from crawford/import
doc: deprecate coreos-ssh-import-*
2015-05-28 13:45:02 -07:00
Alex Crawford
6467f06656 doc: deprecate coreos-ssh-import-* 2015-05-28 13:35:51 -07:00
Alex Crawford
7a05e63fcc coreos-cloudinit: bump to v1.4.1+git 2015-05-12 17:08:27 -07:00
Alex Crawford
ca6f97d050 coreos-cloudinit: bump to v1.4.1 2015-05-12 17:08:06 -07:00
Alex Crawford
d086bca9e4 Merge pull request #336 from crawford/doc
docs: fix typo with etcd2 env vars
2015-04-28 13:48:05 -07:00
Alex Crawford
d25f18776f docs: fix typo with etcd2 env vars 2015-04-27 18:03:13 -07:00
Alex Crawford
c583b77cdb Merge pull request #335 from crawford/github
config: deprecate fetching SSH keys from remote endpoints
2015-04-20 11:29:38 -07:00
Alex Crawford
ed4d5fac4c config: deprecate fetching SSH keys from remote endpoints 2015-04-20 11:23:35 -07:00
Rob Szumski
40429204ba Merge pull request #333 from coreos/robszumski-patch-1
docs: add info about discovery size parameter
2015-04-16 12:04:49 -07:00
Rob Szumski
d72d54be59 docs: add info about discovery size parameter 2015-04-16 12:02:37 -07:00
Alex Crawford
373c7ecbd9 coreos-cloudinit: bump to v1.4.0+git 2015-04-09 17:48:36 -07:00
Alex Crawford
31c46c7051 coreos-cloudinit: bump to v1.4.0 2015-04-09 17:48:14 -07:00
Alex Crawford
66ec7d805c Merge pull request #330 from crawford/etcd
config: add support for etcd2
2015-04-07 14:40:47 -07:00
Alex Crawford
2563896f89 docs: use etcd2 instead of etcd 2015-04-07 14:24:50 -07:00
Alex Crawford
94a242cc58 config: add support for etcd2 2015-04-03 17:29:32 -07:00
Alex Crawford
5b159fcf56 coreos-cloudinit: bump to v1.3.4+git 2015-04-01 14:58:25 -07:00
Alex Crawford
a9e8940132 coreos-cloudinit: bump to v1.3.4 2015-04-01 14:58:09 -07:00
Alex Crawford
cf194ab85e Merge pull request #326 from richardmarshall/user_shell_config
config/system: add shell user attribute
2015-04-01 11:02:15 -07:00
Alex Crawford
33bc5fc63d validate: warn on deprecated keys 2015-03-30 13:52:57 -07:00
Alex Crawford
09f6a279ef config: deprecate etcd2 flags from etcd structure 2015-03-30 13:52:57 -07:00
Richard Marshall
e8c8b811fe docs: add user shell field 2015-03-06 21:12:43 -08:00
Richard Marshall
f5ecc05d62 config/system: add shell user attribute
This adds support for specifying the login shell of created users.
2015-03-06 14:16:19 -08:00
Alex Crawford
66a2f00679 coreos-cloudinit: bump to v1.3.3+git 2015-02-24 12:25:00 -08:00
Alex Crawford
14cad6f7c3 coreos-cloudinit: bump to v1.3.3 2015-02-24 12:24:37 -08:00
Alex Crawford
6f188bd5d4 Merge pull request #319 from Vladimiroff/fix-cloudsigma-empty-ssh-keys
Make sure public ssh key is not empty from CloudSigma's server context
2015-02-23 10:58:17 -08:00
Alex Crawford
41832ab19e Merge pull request #320 from ibuildthecloud/typo-contents
Fix typo, "contents" should be "content"
2015-02-23 10:41:55 -08:00
Darren Shepherd
672e4c07af Fix typo, "contents" should be "content"
The validation of the encoding for write_files was looking
for a node named "contents" when the node name is "content"

Signed-off-by: Darren Shepherd <darren@rancher.com>
2015-02-23 09:17:21 -07:00
Kiril Vladimirov
be53013431 fix(datasource/CloudSigma): Add a test for an empty ssh key 2015-02-22 05:38:57 +02:00
Kiril Vladimirov
c30fc51b03 fix(datasource/CloudSigma): Make sure public ssh key is not empty
Even when public ssh key is not set by the user, CloudSigma's server
context has a key `meta.ssh_public_key` which is just an empty string.
So instead of just relying on the "comma ok" idiom I make sure the value
is not an empty string.
2015-02-21 19:31:01 +02:00
Rob Szumski
b429eaab84 docs: fix formatting 2015-02-18 15:05:28 -08:00
Alex Crawford
e0104e6d93 coreos-cloudinit: bump to v1.3.2+git 2015-02-18 11:13:34 -08:00
Alex Crawford
7bf9712724 coreos-cloudinit: bump to v1.3.2 2015-02-18 11:12:52 -08:00
Alex Crawford
78b0f82918 Merge pull request #318 from crawford/filesystem
configdrive: correct network config reading and improve tests
2015-02-17 13:40:05 -08:00
Alex Crawford
987aa21883 configdrive: check the network config path
Check to make sure that a network config path has been specified before
trying to read from it. Otherwise, it will end up trying to read a
directory.
2015-02-17 13:27:30 -08:00
Alex Crawford
47ac4f6931 test: add directory support to MockFilesystem 2015-02-17 13:27:30 -08:00
Alex Crawford
f8aa7a43b8 coreos-cloudinit: bump to v1.3.1+git 2015-02-13 10:25:01 -08:00
Alex Crawford
2fe0b0b2a8 coreos-cloudinit: bump to v1.3.1 2015-02-13 10:24:41 -08:00
Alex Crawford
19ce7ac849 Merge pull request #317 from crawford/json
configdrive: check metadata length before parsing
2015-02-13 10:22:57 -08:00
Alex Crawford
477053ffde configdrive: check metadata length before parsing
This was lost in some of the recent refactoring.
2015-02-13 10:20:08 -08:00
Alex Crawford
eb0d2dbfa3 coreos-cloudinit: bump to v1.3.0+git 2015-02-11 17:19:32 -08:00
Alex Crawford
18caa5bf07 coreos-cloudinit: bump to v1.3.0 2015-02-11 17:19:05 -08:00
Alex Crawford
a27bbb912f Merge pull request #315 from crawford/cloudsigma
oem: add CloudSigma OEM
2015-02-11 17:15:23 -08:00
Alex Crawford
3b2af743bd oem: add CloudSigma OEM 2015-02-11 17:03:24 -08:00
Alex Crawford
995bc63abe Merge pull request #313 from jimmycuadra/etcd-2.0-configuration
Add etcd 2.0 configuration support
2015-02-09 12:33:28 -08:00
Alex Crawford
a28f870302 Merge pull request #314 from robszumski/master
docs: link to CoreUpdate and Omaha
2015-02-06 14:15:39 -08:00
Rob Szumski
a3357c273c docs: update links 2015-02-06 13:43:06 -08:00
Rob Szumski
080c698ec2 docs: link to CoreUpdate and Omaha 2015-02-06 13:31:50 -08:00
Jimmy Cuadra
afbf1dbb3a Add etcd 2.0 configuration flag support. 2015-02-05 02:57:11 -08:00
Alex Crawford
a275e18533 Merge pull request #308 from demonbane/github-capitalization
Fix GitHub capitalization
2015-01-28 14:28:53 -08:00
Alex Malinovich
cf3baa8805 Fix GitHub capitalization 2015-01-28 14:19:08 -08:00
Jonathan Boulle
ed84bcef04 Merge pull request #307 from jonboulle/master
docs: fix typo
2015-01-28 10:25:15 -08:00
Jonathan Boulle
7d8b29e597 docs: fix typo 2015-01-28 10:19:16 -08:00
Alex Crawford
4eaaa5c927 Merge pull request #304 from crawford/metadata
datasource: improve metadata handling
2015-01-27 14:36:12 -08:00
Alex Crawford
536f8acf2a config: remove network config from CloudConfig 2015-01-26 17:35:08 -08:00
Alex Crawford
9605b5edf2 datasource: remove FetchNetworkConfig step
Its easier to let each datasource grab all metadata in the FetchMetadata
stage than to break it into multiple stages.
2015-01-26 16:08:26 -08:00
Alex Crawford
42153edbbc initialize: change env to process from metadata
We don't use general substitutions so just have env pick the values it
wants to substitute.
2015-01-26 16:08:26 -08:00
Alex Crawford
650a239fdb metadata: simplify merging of metadata
Add an internal field for CloudConfig to make it easier to distinguish.
Instead of creating two CloudConfigs and merging them, just merge the
metadata into the existing CloudConfig.
2015-01-26 16:08:26 -08:00
Alex Crawford
3e47c09b41 datasource: replace metadata map with struct
The loosely-typed metadata map is a load of crap. Make it a struct and
let the compiler help us out.
2015-01-26 15:57:57 -08:00
Alex Crawford
d4c617fc23 config: standardize interface a bit 2015-01-26 15:57:55 -08:00
Alex Crawford
9441586229 test: check all root golang files 2015-01-26 15:57:54 -08:00
Alex Crawford
be62a1df66 test: DRY out MockFilesystem 2015-01-26 15:57:51 -08:00
Jonathan Boulle
c093e44049 Merge pull request #305 from jonboulle/copyright
*: switch to line comments for copyright
2015-01-25 10:28:52 -08:00
Jonathan Boulle
be68a8e5cc *: switch to line comments for copyright
Build tags are not compatible with block comments. Also adds copyright
header to a few places it was missing.
2015-01-24 19:32:33 -08:00
Alex Crawford
58b4de8093 coreos-cloudinit: bump to v1.2.1+git 2015-01-21 14:29:51 -08:00
Alex Crawford
ae3676096c coreos-cloudinit: bump to v1.2.1 2015-01-21 14:29:25 -08:00
Alex Crawford
a548b557ed doc: add coreos-ssh-import-github-users 2015-01-21 14:28:43 -08:00
Alex Crawford
a9c132a706 coreos-cloudinit: bump to v1.2.0+git 2015-01-20 14:42:48 -08:00
Alex Crawford
c3c4b86a3b coreos-cloudinit: bump to v1.2.0 2015-01-20 14:42:18 -08:00
Alex Crawford
44142ff8af Merge pull request #301 from crawford/github
config: add support for multiple github users
2015-01-20 14:26:38 -08:00
Alex Crawford
e9529ede44 config: add support for multiple github users 2015-01-20 13:45:52 -08:00
Alex Crawford
4b5b801171 Merge pull request #295 from crawford/rules
config/validate: add some sanity checks
2015-01-15 16:25:37 -08:00
Alex Crawford
551cbb1e5d config/validate: add rule for file encoding 2015-01-15 15:01:44 -08:00
Alex Crawford
3c93938f8a decode: refactor file decoding into config package 2015-01-15 15:01:44 -08:00
Alex Crawford
f61c08c246 config/validate: add rule for coreos.write_files 2015-01-15 15:01:44 -08:00
Alex Crawford
571903cec6 config/validate: add rule for etcd discovery token 2015-01-15 15:01:44 -08:00
Alex Crawford
bdbd1930ed config/validate: add rule for file paths 2015-01-15 15:01:44 -08:00
Alex Crawford
cc75a943ba Merge pull request #300 from crawford/float
validate: allow promotion of int to float64
2015-01-15 13:17:44 -08:00
Alex Crawford
fc77ba6355 validate: allow promotion of int to float64 2015-01-14 17:54:01 -08:00
Eugene Yakubovich
7cfa0df7c4 Merge pull request #299 from eyakubovich/master
config: document and update flannel config values
2015-01-13 15:55:42 -08:00
Eugene Yakubovich
58f0dadaf9 config: document and update flannel config values
Fixes #297
2015-01-13 15:51:47 -08:00
Michael Marineau
1ab530f157 Merge pull request #293 from realestate-com-au/master
select first available hostname returned by EC2 metadata.
2015-01-05 12:47:27 -08:00
Kevin Yung
13e4b77130 ec2: allow spaces seperated hostname in metadata
AWS hostname metadata will return space seperated hostname and domain
names when DHCPOptionSet is using multiple domain names. This patch will
cater for this scenario.
2015-01-05 16:01:57 +11:00
Alex Crawford
54c62cbb70 coreos-cloudinit: bump to v1.1.0+git 2014-12-30 16:52:10 +01:00
Alex Crawford
c8e864fef5 coreos-cloudinit: bump to v1.1.0 2014-12-30 16:51:24 +01:00
Alex Crawford
60a3377e7c Merge pull request #290 from crawford/yaml
Improved YAML parsing
2014-12-30 16:24:12 +01:00
Alex Crawford
5527f09778 config: fix parsing of file permissions
These reintroduces the braindead '744' syntax for file permissions. Even
though this number isn't octal, it is assumed by convention to be. In
order to pull this off, coerceNodes() was introduced to try to
counteract the type inferrencing that occurs during the yaml
unmarshalling. The config is unmarshalled twice: once into an empty
interface and once into the CloudConfig structure. The two resulting
node structures are combined together. The nodes from the CloudConfig
process replace those from the interface{} when the types of the two
nodes are compatible. For example, with the input `0744`, yaml
interprets that as the integer 484 giving us the nodes '0744'(string)
and 484(int). Because the types string and int are compatible, we opt to
take the string node instead of the integer.
2014-12-30 16:20:21 +01:00
Alex Crawford
54a64454b9 validate: fix printing for non-string values 2014-12-30 16:20:21 +01:00
Alex Crawford
0e70d4f01f config: add validity check for file permissions 2014-12-30 16:20:21 +01:00
Alex Crawford
af8e590575 config: change valid tag to use regexp
A regular expression is much more useful than a list of strings.
2014-12-30 16:20:21 +01:00
Alex Crawford
40d943fb7a reboot-strategy: remove the 'false' value
Since we no longer do a two-stage unmarshal, the 'false' value will no
longer be necessary.
2014-12-30 16:20:21 +01:00
Alex Crawford
248536a5cd config: use a YAML transform to normalize keys
This removes the problematic two-pass unmarshalling.
2014-12-30 16:20:21 +01:00
Alex Crawford
4ed1d03c97 godeps: bump github.com/coreos/yaml 2014-12-30 16:20:20 +01:00
Alex Crawford
057ab37364 config: seperate the CoreOS type from CloudConfig
Renamed Coreos to CoreOS while I was at it.
2014-12-30 16:20:20 +01:00
Alex Crawford
182241c8d3 config: clean up and remove some tests
Small modification to make these align with our test-table-style tests.
Also removed TestCloudConfigInvalidKeys since it hasn't been a useful
test since d3294bcb86.
2014-12-30 16:19:00 +01:00
Michael Marineau
edced59fa6 Merge pull request #281 from thommay/flannel_env_file
Create an environment file for flannel
2014-12-29 15:07:08 -08:00
Thom May
9be836df31 Create an environment file for flannel
Rather than using a systemd overlay, allow docker to load the
environment file. This is due to coreos/coreos-overlay#1002
2014-12-29 10:27:22 +00:00
Jonathan Boulle
4e54447b8e Merge pull request #286 from jonboulle/master
Godeps: switch to coreos/yaml
2014-12-20 15:43:55 -08:00
Jonathan Boulle
999c38b09b Godeps: switch to coreos/yaml 2014-12-20 15:31:02 -08:00
Alex Crawford
06d13de5c3 coreos-cloudinit: bump to v1.0.2+git 2014-12-12 17:38:28 -08:00
Alex Crawford
5b0903d162 coreos-cloudinit: bump to v1.0.2 2014-12-12 17:37:39 -08:00
Alex Crawford
10669be7c0 Merge pull request #284 from crawford/travis
test: disable Travis sudo capability
2014-12-12 17:28:47 -08:00
Alex Crawford
2edae741e1 test: disable Travis sudo capability 2014-12-12 16:46:18 -08:00
Alex Crawford
ea90e553d1 Merge pull request #282 from crawford/network
network: write network units with user units
2014-12-12 15:12:50 -08:00
Alex Crawford
b0cfd86902 network: write network units with user units
This allows us to test the network unit generation as well as removing
some special-cased code.
2014-12-12 15:08:03 -08:00
Alex Crawford
565a9540c9 Merge pull request #283 from crawford/validate
validate: empty user_data is also valid
2014-12-12 15:05:51 -08:00
Alex Crawford
fd10e27b99 validate: empty user_data is also valid 2014-12-12 14:49:42 -08:00
Michael Marineau
39763d772c Merge pull request #280 from marineam/go1.4
travis: Add Go 1.4 as a test target
2014-12-11 16:34:00 -08:00
Michael Marineau
ee69b77bfb travis: Add Go 1.4 as a test target 2014-12-11 15:29:36 -08:00
Jonathan Boulle
353444e56d Merge pull request #279 from cnelson/write_files_encoding_support
Add support for the encoding key to write_files
2014-12-09 17:37:34 -08:00
cnelson
112ba1e31f Added support for the encoding key in write_files
Supported encodings are base64, gzip, and base64 encoded gzip
2014-12-09 17:35:33 -08:00
cnelson
9c3cd9e69c bumped version of yaml.v1 2014-12-09 07:49:59 -08:00
Alex Crawford
685d8317bc Merge pull request #275 from mwhooker/master
Enable configuration of locksmithd
2014-12-05 14:09:40 -08:00
Matthew Hooker
f42d102b26 Also fix wording of Flannel section 2014-12-04 23:55:26 -08:00
Matthew Hooker
c944e9ef94 Enable configuration of locksmithd 2014-12-04 23:53:31 -08:00
Alex Crawford
f10d6e8bef coreos-cloudinit: bump to v1.0.1+git 2014-12-04 16:35:20 -08:00
Alex Crawford
f3f3af79fd coreos-cloudinit: bump to v1.0.1 2014-12-04 16:34:57 -08:00
Alex Crawford
0e63aa0f6b Merge pull request #276 from crawford/networkd
initialize: restart networkd before other units
2014-12-04 16:33:02 -08:00
Alex Crawford
b254e17e89 Merge pull request #263 from robszumski/docs-validator
docs: link to validator
2014-12-04 16:28:21 -08:00
Alex Crawford
5c059b66f0 initialize: restart networkd before other units 2014-12-04 15:25:44 -08:00
Alex Crawford
c628bef666 Merge pull request #273 from crawford/networkd
initialize: only restart networkd once per config
2014-12-02 12:54:27 -08:00
Alex Crawford
2270db3f7a initialize: only restart networkd once per config
Regression introduced by 9fcf338bf3.

Networkd was erroneously being restarted once per network unit. It
should only restart once for the entire config.
2014-12-02 12:46:35 -08:00
Alex Crawford
d0d467813d Merge pull request #251 from Vladimiroff/master
metadata: Populate CloudSigma's IPs properly
2014-12-01 14:52:11 -08:00
Alex Crawford
123f111efe coreos-cloudinit: bump to 1.0.0+git 2014-11-26 14:19:29 -08:00
Alex Crawford
521ecfdab5 coreos-cloudinit: bump to 1.0.0 2014-11-26 14:19:13 -08:00
Alex Crawford
6d0fdf1a47 Merge pull request #268 from crawford/dropins
drop-in: add support for drop-ins
2014-11-26 14:14:49 -08:00
Alex Crawford
ffc54b028c drop-in: add support for drop-ins
This allows a list of drop-ins for a unit to be declared inline within a
cloud-config. For example:

  #cloud-config
  coreos:
    units:
      - name: docker.service
        drop-ins:
          - name: 50-insecure-registry.conf
            content: |
              [Service]
              Environment=DOCKER_OPTS='--insecure-registry="10.0.1.0/24"'
2014-11-26 14:09:35 -08:00
Alex Crawford
420f7cf202 system: clean up TestPlaceUnit() 2014-11-26 10:32:43 -08:00
Alex Crawford
624df676d0 config/unit: move Type() and Group() out of config 2014-11-26 10:32:43 -08:00
Alex Crawford
75ed8dacf9 initialize: clean up TestProcessUnits() 2014-11-26 10:32:43 -08:00
Alex Crawford
dcaabe4d4a system: clean up UnitManager interface 2014-11-26 10:32:43 -08:00
Alex Crawford
92c57423ba Merge pull request #269 from crawford/valid
validate: promote invalid values to an error
2014-11-26 10:32:27 -08:00
Alex Crawford
7447e133c9 validate: promote invalid values to an error 2014-11-26 10:29:09 -08:00
Eugene Yakubovich
4e466c12da Merge pull request #267 from thommay/flannel_unit
the flannel service is called flanneld
2014-11-25 12:30:58 -08:00
Thom May
333468dba3 the flannel service is called flanneld 2014-11-25 14:00:53 +00:00
Alex Crawford
55c3a793ad coreos-cloudinit: bump to 0.11.4+git 2014-11-21 20:11:54 -08:00
Alex Crawford
eca51031c8 coreos-cloudinit: bump to 0.11.4 2014-11-21 20:11:37 -08:00
Alex Crawford
19522bcb82 Merge pull request #266 from crawford/config
config: update configs to match etcd, fleet, and flannel
2014-11-21 20:10:34 -08:00
Alex Crawford
62248ea33d config/fleet: fix configs
Added EtcdKeyPrefix and fixed the types of EngineReconcileInterval and EtcdRequestTimeout.
2014-11-21 16:57:00 -08:00
Alex Crawford
d2a19cc86d config/flannel: correct - vs _ 2014-11-21 16:57:00 -08:00
Alex Crawford
08131ffab1 config/etcd: fix configs
This new table is pulled from the etcd codebase rather than the docs...

Added:
 GraphiteHost
 PeerElectionTimeout
 PeerHeartbeatInterval
 PeerKeyFile
 RetryInterval
 SnapshotCount
 StrTrace
 VeryVeryVerbose

Fixed types:
 ClusterActiveSize
 ClusterRemoveDelay
 ClusterSyncInterval
 HTTPReadTimeout
 HTTPWriteTimeout
 MaxResultBuffer
 MaxRetryAttempts
 Snapshot
 Verbose
 VeryVerbose

Renamed:
 Cors

Removed:
 MaxClusterSize
 CPUProfileFile
2014-11-21 16:57:00 -08:00
Alex Crawford
4a0019c669 config: add support for float64 2014-11-21 16:13:49 -08:00
Alex Crawford
3275ead1ec coreos-cloudinit: bump to 0.11.3+git 2014-11-21 12:25:26 -08:00
Alex Crawford
32b6a55724 coreos-cloudinit: bump to 0.11.3 2014-11-21 12:25:04 -08:00
Alex Crawford
6c43644369 Merge pull request #265 from crawford/update
config/update: add "off" as a valid strategy
2014-11-21 12:22:45 -08:00
Alex Crawford
e6593d49e6 config/update: add "off" as a valid strategy
It was assumed that the user would specify the reboot strategy as an
unquoted value. In the case that they turn off updates, `off` is
interpreted as a boolean and the normalization pass converts that to
`false`. In the event that the user uses `"off"`, it's interpreted as a
string and not modified.
2014-11-21 10:41:03 -08:00
Alex Crawford
ab752b239f coreos-cloudinit: bump to 0.11.2+git 2014-11-20 11:29:25 -08:00
Alex Crawford
0742e4d357 coreos-cloudinit: bump to 0.11.2 2014-11-20 11:29:12 -08:00
Alex Crawford
78f586ec9e Merge pull request #262 from crawford/permissions
config: fix parsing of file permissions
2014-11-20 11:28:11 -08:00
Alex Crawford
6f91b76d79 docs: correct type of permissions 2014-11-20 11:14:44 -08:00
Alex Crawford
5c80ccacc4 config: fix parsing of file permissions
The file permissions can be specified (unfortunately) as a string or an
octal integer. During the normalization step, every field is
unmarshalled into an interface{}. String types are kept in tact but
integers are converted to decimal integers. If the raw config
represented the permissions as an octal, it would be converted to
decimal _before_ it was saved to RawFilePermissions. Permissions() would
then try to convert it again, assuming it was an octal. The new behavior
doesn't assume the radix of the number, allowing decimal and octal
input.
2014-11-20 11:14:44 -08:00
Rob Szumski
44fdf95d99 docs: mention validate flag 2014-11-20 11:12:31 -08:00
Rob Szumski
0a62614eec docs: link to validator 2014-11-20 10:58:57 -08:00
Alex Crawford
97758b343b coreos-cloudinit: bump to 0.11.1+git 2014-11-18 12:14:34 -08:00
Alex Crawford
fb6f52b360 coreos-cloudinit: bump to 0.11.1 2014-11-18 12:14:29 -08:00
Alex Crawford
786cd2a539 Merge pull request #259 from crawford/hyphen
config/validate: disable - vs _ message for now
2014-11-18 12:12:26 -08:00
Alex Crawford
45793f1254 config/validate: disable - vs _ message for now 2014-11-18 12:11:50 -08:00
Alex Crawford
b621756d92 Merge pull request #258 from crawford/header
config/validate: fix line number for header check
2014-11-18 12:11:35 -08:00
Alex Crawford
a5b5c700a6 config/validate: fix line number for header check 2014-11-18 12:02:23 -08:00
Kiril Vladimirov
ea95920f31 fix(datasource/CloudSigma): Make sure DHCP has run 2014-11-17 15:35:10 +02:00
Alex Crawford
d7602f3c08 Merge pull request #244 from eyakubovich/master
flannel: added flannel support and helper to make dropins
2014-11-14 10:46:19 -08:00
Eugene Yakubovich
a20addd05e flannel: added flannel support and helper to make dropins
fleet, flannel, and etcd all generate dropins from config.
To reduce code duplication, factor out a helper to do that.
2014-11-14 10:45:23 -08:00
Alex Crawford
d9d89a6fa0 coreos-cloudinit: bump to 0.11.0+git 2014-11-14 10:42:00 -08:00
Alex Crawford
3c26376326 coreos-cloudinit: bump to 0.11.0 2014-11-14 10:41:47 -08:00
Alex Crawford
d3294bcb86 Merge pull request #254 from crawford/validator
config: add new validator
2014-11-12 17:40:16 -08:00
Alex Crawford
dda314b518 flags: add validate flag
This will allow the user to run a standalone validation.
2014-11-12 16:48:57 -08:00
Alex Crawford
055a3c339a config/validate: add new config validator
This validator is still experimental and is going to need new rules in the
future. This lays out the general framework.
2014-11-12 16:48:57 -08:00
Alex Crawford
51f37100a1 config: remove config validator 2014-11-07 10:18:08 -08:00
Alex Crawford
88e8265cd6 config: seperate AssertValid and AssertStructValid
Added an error structure to make it possible to get the specifics of the failure.
2014-11-07 10:14:34 -08:00
Alex Crawford
6e2db882e6 script: move Script into config package 2014-11-07 10:13:52 -08:00
Alex Crawford
3e2823df1b Merge pull request #256 from crawford/hyphen
config: deprecate - in favor of _ for key names
2014-11-03 14:54:23 -08:00
Alex Crawford
d02aa18839 config: deprecate - in favor of _ for key names
In all of the YAML tags, - has been replaced with _. normalizeConfig() and
normalizeKeys() have also been added to perform the normalization of the input
cloud-config.

As part of the normalization process, falsey values are converted to "false".
The "off" update strategy is no exception and as a result the "off" update
strategy has been changed to "false".
2014-11-03 12:09:52 -08:00
Kiril Vladimirov
b6062f0644 fix(datasource/CloudSigma): Populate local IPv4 address properly 2014-10-23 15:03:23 +03:00
Kiril Vladimirov
c5fada6e69 fix(datasource/CloudSigma): Populate public IPv4 address properly 2014-10-23 13:21:49 +03:00
192 changed files with 22626 additions and 3010 deletions

View File

@@ -1,11 +1,12 @@
language: go language: go
go: sudo: false
- 1.3 matrix:
- 1.2 include:
- go: 1.4
install: install:
- go get code.google.com/p/go.tools/cmd/cover - go get golang.org/x/tools/cmd/cover
- go get code.google.com/p/go.tools/cmd/vet - go get golang.org/x/tools/cmd/vet
- go: 1.5
script: script:
- ./test - ./test

View File

@@ -0,0 +1,38 @@
# Deprecated Cloud-Config Features
## Retrieving SSH Authorized Keys
### From a GitHub User
Using the `coreos-ssh-import-github` field, we can import public SSH keys from a GitHub user to use as authorized keys to a server.
```yaml
#cloud-config
users:
- name: elroy
coreos-ssh-import-github: elroy
```
### From an HTTP Endpoint
We can also pull public SSH keys from any HTTP endpoint which matches [GitHub's API response format](https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user).
For example, if you have an installation of GitHub Enterprise, you can provide a complete URL with an authentication token:
```yaml
#cloud-config
users:
- name: elroy
coreos-ssh-import-url: https://github-enterprise.example.com/api/v3/users/elroy/keys?access_token=<TOKEN>
```
You can also specify any URL whose response matches the JSON format for public keys:
```yaml
#cloud-config
users:
- name: elroy
coreos-ssh-import-url: https://example.com/public-keys
```

View File

@@ -0,0 +1,26 @@
# Cloud-Config Locations
On every boot, coreos-cloudinit looks for a config file to configure your host. Here is a list of locations which are used by the Cloud-Config utility, depending on your CoreOS platform:
Location | Description
--- | --- | ---
|`/media/configvirtfs/openstack/latest/user_data`|`/media/configvirtfs` mount point with [config-2](/os/docs/latest/config-drive.html#contents-and-format) label. It should contain a `openstack/latest/user_data` relative path. Usually used by cloud providers or in VM installations.|
|`/media/configdrive/openstack/latest/user_data`|FAT or ISO9660 filesystem with [config-2](/os/docs/latest/config-drive.html#qemu-virtfs) label and `/media/configdrive/` mount point. It should also contain a `openstack/latest/user_data` relative path. Usually used in installations which are configured by USB Flash sticks or CDROM media.|
|Kernel command line: `cloud-config-url=http://example.com/user_data`.| You can find this string using this command `cat /proc/cmdline`. Usually used in [PXE](/os/docs/latest/booting-with-pxe.html) or [iPXE](/os/docs/latest/booting-with-ipxe.html) boots.|
|`/var/lib/coreos-install/user_data`| When you install CoreOS manually using the [coreos-install](/os/docs/latest/installing-to-disk.html) tool. Usually used in bare metal installations.|
|`/usr/share/oem/cloud-config.yml`| Path for OEM images.|
|`/var/lib/coreos-vagrant/vagrantfile-user-data`| Vagrant OEM scripts automatically store Cloud-Config into this path. |
|`/var/lib/waagent/CustomData`| Azure platform uses OEM path for first Cloud-Config initialization and then `/var/lib/waagent/CustomData` to apply your settings.|
|`http://169.254.169.254/metadata/v1/user-data` `http://169.254.169.254/2009-04-04/user-data` `https://metadata.packet.net/userdata`|DigitalOcean, EC2 and Packet cloud providers correspondingly use these URLs to download Cloud-Config.|
|`/usr/share/oem/bin/vmtoolsd --cmd "info-get guestinfo.coreos.config.data"`|Cloud-Config provided by [VMware Guestinfo][VMware Guestinfo]|
|`/usr/share/oem/bin/vmtoolsd --cmd "info-get guestinfo.coreos.config.url"`|Cloud-Config URL provided by [VMware Guestinfo][VMware Guestinfo]|
[VMware Guestinfo]: vmware-guestinfo.md
You can also run the `coreos-cloudinit` tool manually and provide a path to your custom Cloud-Config file:
```sh
sudo coreos-cloudinit --from-file=/home/core/cloud-config.yaml
```
This command will apply your custom cloud-config.

View File

@@ -17,11 +17,11 @@ For example, the following cloud-config document...
#cloud-config #cloud-config
coreos: coreos:
oem: oem:
id: rackspace id: "rackspace"
name: Rackspace Cloud Servers name: "Rackspace Cloud Servers"
version-id: 168.0.0 version-id: "168.0.0"
home-url: https://www.rackspace.com/cloud/servers/ home-url: "https://www.rackspace.com/cloud/servers/"
bug-report-url: https://github.com/coreos/coreos-overlay bug-report-url: "https://github.com/coreos/coreos-overlay"
``` ```
...would be rendered to the following `/etc/oem-release`: ...would be rendered to the following `/etc/oem-release`:

View File

@@ -1,6 +1,16 @@
# Using Cloud-Config # Using Cloud-Config
CoreOS allows you to declaratively customize various OS-level items, such as network configuration, user accounts, and systemd units. This document describes the full list of items we can configure. The `coreos-cloudinit` program uses these files as it configures the OS after startup or during runtime. Your cloud-config is processed during each boot. CoreOS allows you to declaratively customize various OS-level items, such as network configuration, user accounts, and systemd units. This document describes the full list of items we can configure. The `coreos-cloudinit` program uses these files as it configures the OS after startup or during runtime.
Your cloud-config is processed during each boot. Invalid cloud-config won't be processed but will be logged in the journal. You can validate your cloud-config with the [CoreOS validator]({{site.url}}/validate) or by running `coreos-cloudinit -validate`.
In addition to `coreos-cloudinit -validate` command and https://coreos.com/validate/ online service you can debug `coreos-cloudinit` system output through the `journalctl` tool:
```sh
journalctl _EXE=/usr/bin/coreos-cloudinit
```
It will show `coreos-cloudinit` run output which was triggered by system boot.
## Configuration File ## Configuration File
@@ -16,7 +26,7 @@ We've designed our implementation to allow the same cloud-config file to work ac
The cloud-config file uses the [YAML][yaml] file format, which uses whitespace and new-lines to delimit lists, associative arrays, and values. The cloud-config file uses the [YAML][yaml] file format, which uses whitespace and new-lines to delimit lists, associative arrays, and values.
A cloud-config file should contain `#cloud-config`, followed by an associative array which has zero or more of the following keys: A cloud-config file must contain a header: either `#cloud-config` for processing as cloud-config (suggested) or `#!` for processing as a shell script (advanced). If cloud-config has #cloud-config header, it should followed by an associative array which has zero or more of the following keys:
- `coreos` - `coreos`
- `ssh_authorized_keys` - `ssh_authorized_keys`
@@ -27,6 +37,8 @@ A cloud-config file should contain `#cloud-config`, followed by an associative a
The expected values for these keys are defined in the rest of this document. The expected values for these keys are defined in the rest of this document.
If cloud-config header starts on `#!` then coreos-cloudinit will recognize it as shell script which is interpreted by bash and run it as transient systemd service.
[yaml]: https://en.wikipedia.org/wiki/YAML [yaml]: https://en.wikipedia.org/wiki/YAML
### Providing Cloud-Config with Config-Drive ### Providing Cloud-Config with Config-Drive
@@ -37,7 +49,7 @@ CoreOS tries to conform to each platform's native method to provide user data. E
### coreos ### coreos
#### etcd #### etcd (deprecated. see etcd2)
The `coreos.etcd.*` parameters will be translated to a partial systemd unit acting as an etcd configuration file. The `coreos.etcd.*` parameters will be translated to a partial systemd unit acting as an etcd configuration file.
If the platform environment supports the templating feature of coreos-cloudinit it is possible to automate etcd configuration with the `$private_ipv4` and `$public_ipv4` fields. For example, the following cloud-config document... If the platform environment supports the templating feature of coreos-cloudinit it is possible to automate etcd configuration with the `$private_ipv4` and `$public_ipv4` fields. For example, the following cloud-config document...
@@ -47,15 +59,15 @@ If the platform environment supports the templating feature of coreos-cloudinit
coreos: coreos:
etcd: etcd:
name: node001 name: "node001"
# generate a new token for each unique cluster from https://discovery.etcd.io/new # generate a new token for each unique cluster from https://discovery.etcd.io/new
discovery: https://discovery.etcd.io/<token> discovery: "https://discovery.etcd.io/<token>"
# multi-region and multi-cloud deployments need to use $public_ipv4 # multi-region and multi-cloud deployments need to use $public_ipv4
addr: $public_ipv4:4001 addr: "$public_ipv4:4001"
peer-addr: $private_ipv4:7001 peer-addr: "$private_ipv4:7001"
``` ```
...will generate a systemd unit drop-in like this: ...will generate a systemd unit drop-in for etcd.service with the following contents:
```yaml ```yaml
[Service] [Service]
@@ -66,23 +78,62 @@ Environment="ETCD_PEER_ADDR=192.0.2.13:7001"
``` ```
For more information about the available configuration parameters, see the [etcd documentation][etcd-config]. For more information about the available configuration parameters, see the [etcd documentation][etcd-config].
Note that hyphens in the coreos.etcd.* keys are mapped to underscores.
_Note: The `$private_ipv4` and `$public_ipv4` substitution variables referenced in other documents are only supported on Amazon EC2, Google Compute Engine, OpenStack, Rackspace, DigitalOcean, and Vagrant._ _Note: The `$private_ipv4` and `$public_ipv4` substitution variables referenced in other documents are only supported on Amazon EC2, Google Compute Engine, OpenStack, Rackspace, DigitalOcean, and Vagrant._
[etcd-config]: https://github.com/coreos/etcd/blob/master/Documentation/configuration.md [etcd-config]: https://github.com/coreos/etcd/blob/release-0.4/Documentation/configuration.md
#### etcd2
The `coreos.etcd2.*` parameters will be translated to a partial systemd unit acting as an etcd configuration file.
If the platform environment supports the templating feature of coreos-cloudinit it is possible to automate etcd configuration with the `$private_ipv4` and `$public_ipv4` fields. When generating a [discovery token](https://discovery.etcd.io/new?size=3), set the `size` parameter, since etcd uses this to determine if all members have joined the cluster. After the cluster is bootstrapped, it can grow or shrink from this configured size.
For example, the following cloud-config document...
```yaml
#cloud-config
coreos:
etcd2:
# generate a new token for each unique cluster from https://discovery.etcd.io/new?size=3
discovery: "https://discovery.etcd.io/<token>"
# multi-region and multi-cloud deployments need to use $public_ipv4
advertise-client-urls: "http://$public_ipv4:2379"
initial-advertise-peer-urls: "http://$private_ipv4:2380"
# listen on both the official ports and the legacy ports
# legacy ports can be omitted if your application doesn't depend on them
listen-client-urls: "http://0.0.0.0:2379,http://0.0.0.0:4001"
listen-peer-urls: "http://$private_ipv4:2380,http://$private_ipv4:7001"
```
...will generate a systemd unit drop-in for etcd2.service with the following contents:
```yaml
[Service]
Environment="ETCD_DISCOVERY=https://discovery.etcd.io/<token>"
Environment="ETCD_ADVERTISE_CLIENT_URLS=http://203.0.113.29:2379"
Environment="ETCD_INITIAL_ADVERTISE_PEER_URLS=http://192.0.2.13:2380"
Environment="ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379,http://0.0.0.0:4001"
Environment="ETCD_LISTEN_PEER_URLS=http://192.0.2.13:2380,http://192.0.2.13:7001"
```
For more information about the available configuration parameters, see the [etcd2 documentation][etcd2-config].
_Note: The `$private_ipv4` and `$public_ipv4` substitution variables referenced in other documents are only supported on Amazon EC2, Google Compute Engine, OpenStack, Rackspace, DigitalOcean, and Vagrant._
[etcd2-config]: https://github.com/coreos/etcd/blob/master/Documentation/configuration.md
#### fleet #### fleet
The `coreos.fleet.*` parameters work very similarly to `coreos.etcd.*`, and allow for the configuration of fleet through environment variables. For example, the following cloud-config document... The `coreos.fleet.*` parameters work very similarly to `coreos.etcd2.*`, and allow for the configuration of fleet through environment variables. For example, the following cloud-config document...
```yaml ```yaml
#cloud-config #cloud-config
coreos: coreos:
fleet: fleet:
public-ip: $public_ipv4 public-ip: "$public_ipv4"
metadata: region=us-west metadata: "region=us-west"
``` ```
...will generate a systemd unit drop-in like this: ...will generate a systemd unit drop-in like this:
@@ -93,10 +144,92 @@ Environment="FLEET_PUBLIC_IP=203.0.113.29"
Environment="FLEET_METADATA=region=us-west" Environment="FLEET_METADATA=region=us-west"
``` ```
List of fleet configuration parameters:
- **agent_ttl**: An Agent will be considered dead if it exceeds this amount of time to communicate with the Registry
- **engine_reconcile_interval**: Interval in seconds at which the engine should reconcile the cluster schedule in etcd
- **etcd_cafile**: Path to CA file used for TLS communication with etcd
- **etcd_certfile**: Provide TLS configuration when SSL certificate authentication is enabled in etcd endpoints
- **etcd_keyfile**: Path to private key file used for TLS communication with etcd
- **etcd_key_prefix**: etcd prefix path to be used for fleet keys
- **etcd_request_timeout**: Amount of time in seconds to allow a single etcd request before considering it failed
- **etcd_servers**: Comma separated list of etcd endpoints
- **metadata**: Comma separated key/value pairs that are published with the local to the fleet registry
- **public_ip**: IP accessible by other nodes for inter-host communication
- **verbosity**: Enable debug logging by setting this to an integer value greater than zero
For more information on fleet configuration, see the [fleet documentation][fleet-config]. For more information on fleet configuration, see the [fleet documentation][fleet-config].
[fleet-config]: https://github.com/coreos/fleet/blob/master/Documentation/deployment-and-configuration.md#configuration [fleet-config]: https://github.com/coreos/fleet/blob/master/Documentation/deployment-and-configuration.md#configuration
#### flannel
The `coreos.flannel.*` parameters also work very similarly to `coreos.etcd2.*`
and `coreos.fleet.*`. They can be used to set environment variables for
flanneld. For example, the following cloud-config...
```yaml
#cloud-config
coreos:
flannel:
etcd_prefix: "/coreos.com/network2"
```
...will generate a systemd unit drop-in like so:
```
[Service]
Environment="FLANNELD_ETCD_PREFIX=/coreos.com/network2"
```
List of flannel configuration parameters:
- **etcd_endpoints**: Comma separated list of etcd endpoints
- **etcd_cafile**: Path to CA file used for TLS communication with etcd
- **etcd_certfile**: Path to certificate file used for TLS communication with etcd
- **etcd_keyfile**: Path to private key file used for TLS communication with etcd
- **etcd_prefix**: etcd prefix path to be used for flannel keys
- **ip_masq**: Install IP masquerade rules for traffic outside of flannel subnet
- **subnet_file**: Path to flannel subnet file to write out
- **interface**: Interface (name or IP) that should be used for inter-host communication
- **public_ip**: IP accessible by other nodes for inter-host communication
For more information on flannel configuration, see the [flannel documentation][flannel-readme].
[flannel-readme]: https://github.com/coreos/flannel/blob/master/README.md
#### locksmith
The `coreos.locksmith.*` parameters can be used to set environment variables
for locksmith. For example, the following cloud-config...
```yaml
#cloud-config
coreos:
locksmith:
endpoint: "http://example.com:2379"
```
...will generate a systemd unit drop-in like so:
```
[Service]
Environment="LOCKSMITHD_ENDPOINT=http://example.com:2379"
```
List of locksmith configuration parameters:
- **endpoint**: Comma separated list of etcd endpoints
- **etcd_cafile**: Path to CA file used for TLS communication with etcd
- **etcd_certfile**: Path to certificate file used for TLS communication with etcd
- **etcd_keyfile**: Path to private key file used for TLS communication with etcd
For the complete list of locksmith configuration parameters, see the [locksmith documentation][locksmith-readme].
[locksmith-readme]: https://github.com/coreos/locksmith/blob/master/README.md
#### update #### update
The `coreos.update.*` parameters manipulate settings related to how CoreOS instances are updated. The `coreos.update.*` parameters manipulate settings related to how CoreOS instances are updated.
@@ -109,9 +242,12 @@ The `reboot-strategy` parameter also affects the behaviour of [locksmith](https:
- _etcd-lock_: Reboot after first taking a distributed lock in etcd, this guarantees that only one host will reboot concurrently and that the cluster will remain available during the update. - _etcd-lock_: Reboot after first taking a distributed lock in etcd, this guarantees that only one host will reboot concurrently and that the cluster will remain available during the update.
- _best-effort_ - If etcd is running, "etcd-lock", otherwise simply "reboot". - _best-effort_ - If etcd is running, "etcd-lock", otherwise simply "reboot".
- _off_ - Disable rebooting after updates are applied (not recommended). - _off_ - Disable rebooting after updates are applied (not recommended).
- **server**: is the omaha endpoint URL which will be queried for updates. - **server**: The location of the [CoreUpdate][coreupdate] server which will be queried for updates. Also known as the [omaha][omaha-docs] server endpoint.
- **group**: signifies the channel which should be used for automatic updates. This value defaults to the version of the image initially downloaded. (one of "master", "alpha", "beta", "stable") - **group**: signifies the channel which should be used for automatic updates. This value defaults to the version of the image initially downloaded. (one of "master", "alpha", "beta", "stable")
[coreupdate]: https://coreos.com/products/coreupdate
[omaha-docs]: https://coreos.com/docs/coreupdate/custom-apps/coreupdate-protocol/
*Note: cloudinit will only manipulate the locksmith unit file in the systemd runtime directory (`/run/systemd/system/locksmithd.service`). If any manual modifications are made to an overriding unit configuration file (e.g. `/etc/systemd/system/locksmithd.service`), cloudinit will no longer be able to control the locksmith service unit.* *Note: cloudinit will only manipulate the locksmith unit file in the systemd runtime directory (`/run/systemd/system/locksmithd.service`). If any manual modifications are made to an overriding unit configuration file (e.g. `/etc/systemd/system/locksmithd.service`), cloudinit will no longer be able to control the locksmith service unit.*
##### Example ##### Example
@@ -120,7 +256,7 @@ The `reboot-strategy` parameter also affects the behaviour of [locksmith](https:
#cloud-config #cloud-config
coreos: coreos:
update: update:
reboot-strategy: etcd-lock reboot-strategy: "etcd-lock"
``` ```
#### units #### units
@@ -135,6 +271,10 @@ Each item is an object with the following fields:
- **content**: Plaintext string representing entire unit file. If no value is provided, the unit is assumed to exist already. - **content**: Plaintext string representing entire unit file. If no value is provided, the unit is assumed to exist already.
- **command**: Command to execute on unit: start, stop, reload, restart, try-restart, reload-or-restart, reload-or-try-restart. The default behavior is to not execute any commands. - **command**: Command to execute on unit: start, stop, reload, restart, try-restart, reload-or-restart, reload-or-try-restart. The default behavior is to not execute any commands.
- **mask**: Whether to mask the unit file by symlinking it to `/dev/null` (analogous to `systemctl mask <name>`). Note that unlike `systemctl mask`, **this will destructively remove any existing unit file** located at `/etc/systemd/system/<unit>`, to ensure that the mask succeeds. The default value is false. - **mask**: Whether to mask the unit file by symlinking it to `/dev/null` (analogous to `systemctl mask <name>`). Note that unlike `systemctl mask`, **this will destructively remove any existing unit file** located at `/etc/systemd/system/<unit>`, to ensure that the mask succeeds. The default value is false.
- **drop-ins**: A list of unit drop-ins with the following fields:
- **name**: String representing unit's name. Required.
- **content**: Plaintext string representing entire file. Required.
**NOTE:** The command field is ignored for all network, netdev, and link units. The systemd-networkd.service unit will be restarted in their place. **NOTE:** The command field is ignored for all network, netdev, and link units. The systemd-networkd.service unit will be restarted in their place.
@@ -147,8 +287,8 @@ Write a unit to disk, automatically starting it.
coreos: coreos:
units: units:
- name: docker-redis.service - name: "docker-redis.service"
command: start command: "start"
content: | content: |
[Unit] [Unit]
Description=Redis container Description=Redis container
@@ -161,17 +301,32 @@ coreos:
ExecStop=/usr/bin/docker stop -t 2 redis_server ExecStop=/usr/bin/docker stop -t 2 redis_server
``` ```
Start the built-in `etcd` and `fleet` services: Add the DOCKER_OPTS environment variable to docker.service.
```yaml ```yaml
#cloud-config #cloud-config
coreos: coreos:
units: units:
- name: etcd.service - name: "docker.service"
command: start drop-ins:
- name: fleet.service - name: "50-insecure-registry.conf"
command: start content: |
[Service]
Environment=DOCKER_OPTS='--insecure-registry="10.0.1.0/24"'
```
Start the built-in `etcd2` and `fleet` services:
```yaml
#cloud-config
coreos:
units:
- name: "etcd2.service"
command: "start"
- name: "fleet.service"
command: "start"
``` ```
### ssh_authorized_keys ### ssh_authorized_keys
@@ -185,7 +340,7 @@ Override this by using the `--ssh-key-name` flag when calling `coreos-cloudinit`
#cloud-config #cloud-config
ssh_authorized_keys: ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0g+ZTxC7weoIJLUafOgrm+h... - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0g+ZTxC7weoIJLUafOgrm+h..."
``` ```
### hostname ### hostname
@@ -196,7 +351,7 @@ This is the local part of a fully-qualified domain name (i.e. `foo` in `foo.exam
```yaml ```yaml
#cloud-config #cloud-config
hostname: coreos1 hostname: "coreos1"
``` ```
### users ### users
@@ -213,10 +368,12 @@ All but the `passwd` and `ssh-authorized-keys` fields will be ignored if the use
- **groups**: Add user to these additional groups - **groups**: Add user to these additional groups
- **no-user-group**: Boolean. Skip default group creation. - **no-user-group**: Boolean. Skip default group creation.
- **ssh-authorized-keys**: List of public SSH keys to authorize for this user - **ssh-authorized-keys**: List of public SSH keys to authorize for this user
- **coreos-ssh-import-github**: Authorize SSH keys from Github user - **coreos-ssh-import-github** [DEPRECATED]: Authorize SSH keys from GitHub user
- **coreos-ssh-import-url**: Authorize SSH keys imported from a url endpoint. - **coreos-ssh-import-github-users** [DEPRECATED]: Authorize SSH keys from a list of GitHub users
- **coreos-ssh-import-url** [DEPRECATED]: Authorize SSH keys imported from a url endpoint.
- **system**: Create the user as a system user. No home directory will be created. - **system**: Create the user as a system user. No home directory will be created.
- **no-log-init**: Boolean. Skip initialization of lastlog and faillog databases. - **no-log-init**: Boolean. Skip initialization of lastlog and faillog databases.
- **shell**: User's login shell.
The following fields are not yet implemented: The following fields are not yet implemented:
@@ -230,13 +387,13 @@ The following fields are not yet implemented:
#cloud-config #cloud-config
users: users:
- name: elroy - name: "elroy"
passwd: $6$5s2u6/jR$un0AvWnqilcgaNB3Mkxd5yYv6mTlWfOoCYHZmfi3LDKVltj.E8XNKEcwWm... passwd: "$6$5s2u6/jR$un0AvWnqilcgaNB3Mkxd5yYv6mTlWfOoCYHZmfi3LDKVltj.E8XNKEcwWm..."
groups: groups:
- sudo - "sudo"
- docker - "docker"
ssh-authorized-keys: ssh-authorized-keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0g+ZTxC7weoIJLUafOgrm+h... - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0g+ZTxC7weoIJLUafOgrm+h..."
``` ```
#### Generating a password hash #### Generating a password hash
@@ -259,43 +416,6 @@ perl -e 'print crypt("password","\$6\$SALT\$") . "\n"'
Using a higher number of rounds will help create more secure passwords, but given enough time, password hashes can be reversed. On most RPM based distributions there is a tool called mkpasswd available in the `expect` package, but this does not handle "rounds" nor advanced hashing algorithms. Using a higher number of rounds will help create more secure passwords, but given enough time, password hashes can be reversed. On most RPM based distributions there is a tool called mkpasswd available in the `expect` package, but this does not handle "rounds" nor advanced hashing algorithms.
#### Retrieving SSH Authorized Keys
##### From a GitHub User
Using the `coreos-ssh-import-github` field, we can import public SSH keys from a GitHub user to use as authorized keys to a server.
```yaml
#cloud-config
users:
- name: elroy
coreos-ssh-import-github: elroy
```
##### From an HTTP Endpoint
We can also pull public SSH keys from any HTTP endpoint which matches [GitHub's API response format](https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user).
For example, if you have an installation of GitHub Enterprise, you can provide a complete URL with an authentication token:
```yaml
#cloud-config
users:
- name: elroy
coreos-ssh-import-url: https://github-enterprise.example.com/api/v3/users/elroy/keys?access_token=<TOKEN>
```
You can also specify any URL whose response matches the JSON format for public keys:
```yaml
#cloud-config
users:
- name: elroy
coreos-ssh-import-url: https://example.com/public-keys
```
### write_files ### write_files
The `write_files` directive defines a set of files to create on the local filesystem. The `write_files` directive defines a set of files to create on the local filesystem.
@@ -303,25 +423,45 @@ Each item in the list may have the following keys:
- **path**: Absolute location on disk where contents should be written - **path**: Absolute location on disk where contents should be written
- **content**: Data to write at the provided `path` - **content**: Data to write at the provided `path`
- **permissions**: String representing file permissions in octal notation (i.e. '0644') - **permissions**: Integer representing file permissions, typically in octal notation (i.e. 0644)
- **owner**: User and group that should own the file written to disk. This is equivalent to the `<user>:<group>` argument to `chown <user>:<group> <path>`. - **owner**: User and group that should own the file written to disk. This is equivalent to the `<user>:<group>` argument to `chown <user>:<group> <path>`.
- **encoding**: Optional. The encoding of the data in content. If not specified this defaults to the yaml document encoding (usually utf-8). Supported encoding types are:
- **b64, base64**: Base64 encoded content
- **gz, gzip**: gzip encoded content, for use with the !!binary tag
- **gz+b64, gz+base64, gzip+b64, gzip+base64**: Base64 encoded gzip content
Explicitly not implemented is the **encoding** attribute.
The **content** field must represent exactly what should be written to disk.
```yaml ```yaml
#cloud-config #cloud-config
write_files: write_files:
- path: /etc/resolv.conf - path: "/etc/resolv.conf"
permissions: 0644 permissions: "0644"
owner: root owner: "root"
content: | content: |
nameserver 8.8.8.8 nameserver 8.8.8.8
- path: /etc/motd - path: "/etc/motd"
permissions: 0644 permissions: "0644"
owner: root owner: "root"
content: | content: |
Good news, everyone! Good news, everyone!
- path: "/tmp/like_this"
permissions: "0644"
owner: "root"
encoding: "gzip"
content: !!binary |
H4sIAKgdh1QAAwtITM5WyK1USMqvUCjPLMlQSMssS1VIya9KzVPIySwszS9SyCpNLwYARQFQ5CcAAAA=
- path: "/tmp/or_like_this"
permissions: "0644"
owner: "root"
encoding: "gzip+base64"
content: |
H4sIAKgdh1QAAwtITM5WyK1USMqvUCjPLMlQSMssS1VIya9KzVPIySwszS9SyCpNLwYARQFQ5CcAAAA=
- path: "/tmp/todolist"
permissions: "0644"
owner: "root"
encoding: "base64"
content: |
UGFjayBteSBib3ggd2l0aCBmaXZlIGRvemVuIGxpcXVvciBqdWdz
``` ```
### manage_etc_hosts ### manage_etc_hosts
@@ -334,5 +474,5 @@ infrastructure in place to resolve its own hostname, for example, when using Vag
```yaml ```yaml
#cloud-config #cloud-config
manage_etc_hosts: localhost manage_etc_hosts: "localhost"
``` ```

View File

@@ -4,7 +4,7 @@ CoreOS supports providing configuration data via [config drive][config-drive]
disk images. Currently only providing a single script or cloud config file is disk images. Currently only providing a single script or cloud config file is
supported. supported.
[config-drive]: http://docs.openstack.org/user-guide/content/enable_config_drive.html#config_drive_contents [config-drive]: http://docs.openstack.org/user-guide/cli_config_drive.html
## Contents and Format ## Contents and Format
@@ -21,6 +21,12 @@ mkisofs -R -V config-2 -o configdrive.iso /tmp/new-drive
rm -r /tmp/new-drive rm -r /tmp/new-drive
``` ```
If on OS X, replace the `mkisofs` invocation with:
```sh
hdiutil makehybrid -iso -joliet -default-volume-name config-2 -o configdrive.iso /tmp/new-drive
```
## QEMU virtfs ## QEMU virtfs
One exception to the above, when using QEMU it is possible to skip creating an One exception to the above, when using QEMU it is possible to skip creating an

View File

@@ -0,0 +1,35 @@
# VMWare Guestinfo Interface
## Cloud-Config VMWare Guestinfo Variables
coreos-cloudinit accepts configuration from the VMware RPC API's *guestinfo*
facility. This datasource can be enabled with the `--from-vmware-guestinfo`
flag to coreos-cloudinit.
The following guestinfo variables are recognized and processed by cloudinit
when passed from the hypervisor to the virtual machine at boot time. Note that
property names are prefixed with `guestinfo.` in the VMX, e.g., `guestinfo.hostname`.
| guestinfo variable | type |
|:--------------------------------------|:--------------------------------|
| `hostname` | `hostname` |
| `interface.<n>.name` | `string` |
| `interface.<n>.mac` | `MAC address` |
| `interface.<n>.dhcp` | `{"yes", "no"}` |
| `interface.<n>.role` | `{"public", "private"}` |
| `interface.<n>.ip.<m>.address` | `CIDR IP address` |
| `interface.<n>.route.<l>.gateway` | `IP address` |
| `interface.<n>.route.<l>.destination` | `CIDR IP address` |
| `dns.server.<x>` | `IP address` |
| `coreos.config.data` | `string` |
| `coreos.config.data.encoding` | `{"", "base64", "gzip+base64"}` |
| `coreos.config.url` | `URL` |
Note: "n", "m", "l", and "x" are 0-indexed, incrementing integers. The
identifier for an `interface` does not correspond to anything outside of this
configuration; it serves only to distinguish between multiple `interface`s.
The guide to [booting on VMWare][bootvmware] is the starting point for more
information about configuring and running CoreOS on VMWare.
[bootvmware]: https://github.com/coreos/docs/blob/master/os/booting-on-vmware.md

10
Godeps/Godeps.json generated
View File

@@ -1,6 +1,6 @@
{ {
"ImportPath": "github.com/coreos/coreos-cloudinit", "ImportPath": "github.com/coreos/coreos-cloudinit",
"GoVersion": "go1.3.1", "GoVersion": "go1.3.3",
"Packages": [ "Packages": [
"./..." "./..."
], ],
@@ -13,6 +13,10 @@
"ImportPath": "github.com/coreos/go-systemd/dbus", "ImportPath": "github.com/coreos/go-systemd/dbus",
"Rev": "4fbc5060a317b142e6c7bfbedb65596d5f0ab99b" "Rev": "4fbc5060a317b142e6c7bfbedb65596d5f0ab99b"
}, },
{
"ImportPath": "github.com/coreos/yaml",
"Rev": "6b16a5714269b2f70720a45406b1babd947a17ef"
},
{ {
"ImportPath": "github.com/dotcloud/docker/pkg/netlink", "ImportPath": "github.com/dotcloud/docker/pkg/netlink",
"Comment": "v0.11.1-359-g55d41c3e21e1", "Comment": "v0.11.1-359-g55d41c3e21e1",
@@ -27,8 +31,8 @@
"Rev": "cdabc8d44e8e84f58f18074ae44337e1f2f375b9" "Rev": "cdabc8d44e8e84f58f18074ae44337e1f2f375b9"
}, },
{ {
"ImportPath": "gopkg.in/yaml.v1", "ImportPath": "github.com/sigma/vmw-guestinfo",
"Rev": "feb4ca79644e8e7e39c06095246ee54b1282c118" "Rev": "de573afc542e0268fe8478d46e237fad9d6f7aec"
} }
] ]
} }

View File

@@ -1,3 +1,6 @@
Copyright (c) 2011-2014 - Canonical Inc.
This software is licensed under the LGPLv3, included below. This software is licensed under the LGPLv3, included below.
As a special exception to the GNU Lesser General Public License version 3 As a special exception to the GNU Lesser General Public License version 3

View File

@@ -1,3 +1,6 @@
Note: This is a fork of https://github.com/go-yaml/yaml. The following README
doesn't necessarily apply to this fork.
# YAML support for the Go language # YAML support for the Go language
Introduction Introduction
@@ -12,10 +15,10 @@ C library to parse and generate YAML data quickly and reliably.
Compatibility Compatibility
------------- -------------
The yaml package is almost compatible with YAML 1.1, including support for The yaml package supports most of YAML 1.1 and 1.2, including support for
anchors, tags, etc. There are still a few missing bits, such as document anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
merging, base-60 floats (huh?), and multi-document unmarshalling. These implemented, and base-60 floats from YAML 1.1 are purposefully not
features are not hard to add, and will be introduced as necessary. supported since they're a poor design and are gone in YAML 1.2.
Installation and usage Installation and usage
---------------------- ----------------------

View File

@@ -1,6 +1,8 @@
package yaml package yaml
import ( import (
"encoding/base64"
"fmt"
"reflect" "reflect"
"strconv" "strconv"
"time" "time"
@@ -31,10 +33,12 @@ type parser struct {
parser yaml_parser_t parser yaml_parser_t
event yaml_event_t event yaml_event_t
doc *node doc *node
transform transformString
} }
func newParser(b []byte) *parser { func newParser(b []byte, t transformString) *parser {
p := parser{} p := parser{transform: t}
if !yaml_parser_initialize(&p.parser) { if !yaml_parser_initialize(&p.parser) {
panic("Failed to initialize YAML emitter") panic("Failed to initialize YAML emitter")
} }
@@ -63,7 +67,7 @@ func (p *parser) destroy() {
func (p *parser) skip() { func (p *parser) skip() {
if p.event.typ != yaml_NO_EVENT { if p.event.typ != yaml_NO_EVENT {
if p.event.typ == yaml_STREAM_END_EVENT { if p.event.typ == yaml_STREAM_END_EVENT {
panic("Attempted to go past the end of stream. Corrupted value?") fail("Attempted to go past the end of stream. Corrupted value?")
} }
yaml_event_delete(&p.event) yaml_event_delete(&p.event)
} }
@@ -89,7 +93,7 @@ func (p *parser) fail() {
} else { } else {
msg = "Unknown problem parsing YAML content" msg = "Unknown problem parsing YAML content"
} }
panic(where + msg) fail(where + msg)
} }
func (p *parser) anchor(n *node, anchor []byte) { func (p *parser) anchor(n *node, anchor []byte) {
@@ -114,10 +118,9 @@ func (p *parser) parse() *node {
// Happens when attempting to decode an empty buffer. // Happens when attempting to decode an empty buffer.
return nil return nil
default: default:
panic("Attempted to parse unknown event: " + panic("Attempted to parse unknown event: " + strconv.Itoa(int(p.event.typ)))
strconv.Itoa(int(p.event.typ)))
} }
panic("Unreachable") panic("unreachable")
} }
func (p *parser) node(kind int) *node { func (p *parser) node(kind int) *node {
@@ -135,8 +138,7 @@ func (p *parser) document() *node {
p.skip() p.skip()
n.children = append(n.children, p.parse()) n.children = append(n.children, p.parse())
if p.event.typ != yaml_DOCUMENT_END_EVENT { if p.event.typ != yaml_DOCUMENT_END_EVENT {
panic("Expected end of document event but got " + panic("Expected end of document event but got " + strconv.Itoa(int(p.event.typ)))
strconv.Itoa(int(p.event.typ)))
} }
p.skip() p.skip()
return n return n
@@ -175,7 +177,10 @@ func (p *parser) mapping() *node {
p.anchor(n, p.event.anchor) p.anchor(n, p.event.anchor)
p.skip() p.skip()
for p.event.typ != yaml_MAPPING_END_EVENT { for p.event.typ != yaml_MAPPING_END_EVENT {
n.children = append(n.children, p.parse(), p.parse()) key := p.parse()
key.value = p.transform(key.value)
value := p.parse()
n.children = append(n.children, key, value)
} }
p.skip() p.skip()
return n return n
@@ -218,7 +223,7 @@ func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (set func()
var arg interface{} var arg interface{}
*out = reflect.ValueOf(&arg).Elem() *out = reflect.ValueOf(&arg).Elem()
return func() { return func() {
*good = setter.SetYAML(tag, arg) *good = setter.SetYAML(shortTag(tag), arg)
} }
} }
} }
@@ -226,7 +231,7 @@ func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (set func()
for again { for again {
again = false again = false
setter, _ := (*out).Interface().(Setter) setter, _ := (*out).Interface().(Setter)
if tag != "!!null" || setter != nil { if tag != yaml_NULL_TAG || setter != nil {
if pv := (*out); pv.Kind() == reflect.Ptr { if pv := (*out); pv.Kind() == reflect.Ptr {
if pv.IsNil() { if pv.IsNil() {
*out = reflect.New(pv.Type().Elem()).Elem() *out = reflect.New(pv.Type().Elem()).Elem()
@@ -242,7 +247,7 @@ func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (set func()
var arg interface{} var arg interface{}
*out = reflect.ValueOf(&arg).Elem() *out = reflect.ValueOf(&arg).Elem()
return func() { return func() {
*good = setter.SetYAML(tag, arg) *good = setter.SetYAML(shortTag(tag), arg)
} }
} }
} }
@@ -279,10 +284,10 @@ func (d *decoder) document(n *node, out reflect.Value) (good bool) {
func (d *decoder) alias(n *node, out reflect.Value) (good bool) { func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
an, ok := d.doc.anchors[n.value] an, ok := d.doc.anchors[n.value]
if !ok { if !ok {
panic("Unknown anchor '" + n.value + "' referenced") fail("Unknown anchor '" + n.value + "' referenced")
} }
if d.aliases[n.value] { if d.aliases[n.value] {
panic("Anchor '" + n.value + "' value contains itself") fail("Anchor '" + n.value + "' value contains itself")
} }
d.aliases[n.value] = true d.aliases[n.value] = true
good = d.unmarshal(an, out) good = d.unmarshal(an, out)
@@ -290,23 +295,50 @@ func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
return good return good
} }
var zeroValue reflect.Value
func resetMap(out reflect.Value) {
for _, k := range out.MapKeys() {
out.SetMapIndex(k, zeroValue)
}
}
var durationType = reflect.TypeOf(time.Duration(0)) var durationType = reflect.TypeOf(time.Duration(0))
func (d *decoder) scalar(n *node, out reflect.Value) (good bool) { func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
var tag string var tag string
var resolved interface{} var resolved interface{}
if n.tag == "" && !n.implicit { if n.tag == "" && !n.implicit {
tag = "!!str" tag = yaml_STR_TAG
resolved = n.value resolved = n.value
} else { } else {
tag, resolved = resolve(n.tag, n.value) tag, resolved = resolve(n.tag, n.value)
if tag == yaml_BINARY_TAG {
data, err := base64.StdEncoding.DecodeString(resolved.(string))
if err != nil {
fail("!!binary value contains invalid base64 data")
}
resolved = string(data)
}
} }
if set := d.setter(tag, &out, &good); set != nil { if set := d.setter(tag, &out, &good); set != nil {
defer set() defer set()
} }
if resolved == nil {
if out.Kind() == reflect.Map && !out.CanAddr() {
resetMap(out)
} else {
out.Set(reflect.Zero(out.Type()))
}
good = true
return
}
switch out.Kind() { switch out.Kind() {
case reflect.String: case reflect.String:
if resolved != nil { if tag == yaml_BINARY_TAG {
out.SetString(resolved.(string))
good = true
} else if resolved != nil {
out.SetString(n.value) out.SetString(n.value)
good = true good = true
} }
@@ -380,11 +412,6 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
good = true good = true
} }
case reflect.Ptr: case reflect.Ptr:
switch resolved.(type) {
case nil:
out.Set(reflect.Zero(out.Type()))
good = true
default:
if out.Type().Elem() == reflect.TypeOf(resolved) { if out.Type().Elem() == reflect.TypeOf(resolved) {
elem := reflect.New(out.Type().Elem()) elem := reflect.New(out.Type().Elem())
elem.Elem().Set(reflect.ValueOf(resolved)) elem.Elem().Set(reflect.ValueOf(resolved))
@@ -392,7 +419,6 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
good = true good = true
} }
} }
}
return good return good
} }
@@ -404,7 +430,7 @@ func settableValueOf(i interface{}) reflect.Value {
} }
func (d *decoder) sequence(n *node, out reflect.Value) (good bool) { func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
if set := d.setter("!!seq", &out, &good); set != nil { if set := d.setter(yaml_SEQ_TAG, &out, &good); set != nil {
defer set() defer set()
} }
var iface reflect.Value var iface reflect.Value
@@ -433,7 +459,7 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
} }
func (d *decoder) mapping(n *node, out reflect.Value) (good bool) { func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
if set := d.setter("!!map", &out, &good); set != nil { if set := d.setter(yaml_MAP_TAG, &out, &good); set != nil {
defer set() defer set()
} }
if out.Kind() == reflect.Struct { if out.Kind() == reflect.Struct {
@@ -465,6 +491,13 @@ func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
} }
k := reflect.New(kt).Elem() k := reflect.New(kt).Elem()
if d.unmarshal(n.children[i], k) { if d.unmarshal(n.children[i], k) {
kkind := k.Kind()
if kkind == reflect.Interface {
kkind = k.Elem().Kind()
}
if kkind == reflect.Map || kkind == reflect.Slice {
fail(fmt.Sprintf("invalid map key: %#v", k.Interface()))
}
e := reflect.New(et).Elem() e := reflect.New(et).Elem()
if d.unmarshal(n.children[i+1], e) { if d.unmarshal(n.children[i+1], e) {
out.SetMapIndex(k, e) out.SetMapIndex(k, e)
@@ -511,7 +544,7 @@ func (d *decoder) merge(n *node, out reflect.Value) {
case aliasNode: case aliasNode:
an, ok := d.doc.anchors[n.value] an, ok := d.doc.anchors[n.value]
if ok && an.kind != mappingNode { if ok && an.kind != mappingNode {
panic(wantMap) fail(wantMap)
} }
d.unmarshal(n, out) d.unmarshal(n, out)
case sequenceNode: case sequenceNode:
@@ -521,18 +554,18 @@ func (d *decoder) merge(n *node, out reflect.Value) {
if ni.kind == aliasNode { if ni.kind == aliasNode {
an, ok := d.doc.anchors[ni.value] an, ok := d.doc.anchors[ni.value]
if ok && an.kind != mappingNode { if ok && an.kind != mappingNode {
panic(wantMap) fail(wantMap)
} }
} else if ni.kind != mappingNode { } else if ni.kind != mappingNode {
panic(wantMap) fail(wantMap)
} }
d.unmarshal(ni, out) d.unmarshal(ni, out)
} }
default: default:
panic(wantMap) fail(wantMap)
} }
} }
func isMerge(n *node) bool { func isMerge(n *node) bool {
return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == "!!merge" || n.tag == "tag:yaml.org,2002:merge") return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG)
} }

View File

@@ -1,10 +1,11 @@
package yaml_test package yaml_test
import ( import (
"github.com/coreos/yaml"
. "gopkg.in/check.v1" . "gopkg.in/check.v1"
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/gopkg.in/yaml.v1"
"math" "math"
"reflect" "reflect"
"strings"
"time" "time"
) )
@@ -316,7 +317,10 @@ var unmarshalTests = []struct {
map[string]*string{"foo": new(string)}, map[string]*string{"foo": new(string)},
}, { }, {
"foo: null", "foo: null",
map[string]string{}, map[string]string{"foo": ""},
}, {
"foo: null",
map[string]interface{}{"foo": nil},
}, },
// Ignored field // Ignored field
@@ -377,6 +381,24 @@ var unmarshalTests = []struct {
"a: <foo>", "a: <foo>",
map[string]string{"a": "<foo>"}, map[string]string{"a": "<foo>"},
}, },
// Base 60 floats are obsolete and unsupported.
{
"a: 1:1\n",
map[string]string{"a": "1:1"},
},
// Binary data.
{
"a: !!binary gIGC\n",
map[string]string{"a": "\x80\x81\x82"},
}, {
"a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
map[string]string{"a": strings.Repeat("\x90", 54)},
}, {
"a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n",
map[string]string{"a": strings.Repeat("\x00", 52)},
},
} }
type inlineB struct { type inlineB struct {
@@ -424,12 +446,15 @@ func (s *S) TestUnmarshalNaN(c *C) {
var unmarshalErrorTests = []struct { var unmarshalErrorTests = []struct {
data, error string data, error string
}{ }{
{"v: !!float 'error'", "YAML error: Can't decode !!str 'error' as a !!float"}, {"v: !!float 'error'", "YAML error: cannot decode !!str `error` as a !!float"},
{"v: [A,", "YAML error: line 1: did not find expected node content"}, {"v: [A,", "YAML error: line 1: did not find expected node content"},
{"v:\n- [A,", "YAML error: line 2: did not find expected node content"}, {"v:\n- [A,", "YAML error: line 2: did not find expected node content"},
{"a: *b\n", "YAML error: Unknown anchor 'b' referenced"}, {"a: *b\n", "YAML error: Unknown anchor 'b' referenced"},
{"a: &a\n b: *a\n", "YAML error: Anchor 'a' value contains itself"}, {"a: &a\n b: *a\n", "YAML error: Anchor 'a' value contains itself"},
{"value: -", "YAML error: block sequence entries are not allowed in this context"}, {"value: -", "YAML error: block sequence entries are not allowed in this context"},
{"a: !!binary ==", "YAML error: !!binary value contains invalid base64 data"},
{"{[.]}", `YAML error: invalid map key: \[\]interface \{\}\{"\."\}`},
{"{{.}}", `YAML error: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`},
} }
func (s *S) TestUnmarshalErrors(c *C) { func (s *S) TestUnmarshalErrors(c *C) {
@@ -532,6 +557,23 @@ func (s *S) TestUnmarshalWithFalseSetterIgnoresValue(c *C) {
c.Assert(m["ghi"].value, Equals, 3) c.Assert(m["ghi"].value, Equals, 3)
} }
func (s *S) TestUnmarshalWithTransform(c *C) {
data := `{a_b: 1, c-d: 2, e-f_g: 3, h_i-j: 4}`
expect := map[string]int{
"a_b": 1,
"c_d": 2,
"e_f_g": 3,
"h_i_j": 4,
}
m := map[string]int{}
yaml.UnmarshalMappingKeyTransform = func(i string) string {
return strings.Replace(i, "-", "_", -1)
}
err := yaml.Unmarshal([]byte(data), m)
c.Assert(err, IsNil)
c.Assert(m, DeepEquals, expect)
}
// From http://yaml.org/type/merge.html // From http://yaml.org/type/merge.html
var mergeTests = ` var mergeTests = `
anchors: anchors:
@@ -624,6 +666,30 @@ func (s *S) TestMergeStruct(c *C) {
} }
} }
var unmarshalNullTests = []func() interface{}{
func() interface{} { var v interface{}; v = "v"; return &v },
func() interface{} { var s = "s"; return &s },
func() interface{} { var s = "s"; sptr := &s; return &sptr },
func() interface{} { var i = 1; return &i },
func() interface{} { var i = 1; iptr := &i; return &iptr },
func() interface{} { m := map[string]int{"s": 1}; return &m },
func() interface{} { m := map[string]int{"s": 1}; return m },
}
func (s *S) TestUnmarshalNull(c *C) {
for _, test := range unmarshalNullTests {
item := test()
zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface()
err := yaml.Unmarshal([]byte("null"), item)
c.Assert(err, IsNil)
if reflect.TypeOf(item).Kind() == reflect.Map {
c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface())
} else {
c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero)
}
}
}
//var data []byte //var data []byte
//func init() { //func init() {
// var err error // var err error

View File

@@ -973,9 +973,9 @@ func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
if bytes.HasPrefix(tag, tag_directive.prefix) { if bytes.HasPrefix(tag, tag_directive.prefix) {
emitter.tag_data.handle = tag_directive.handle emitter.tag_data.handle = tag_directive.handle
emitter.tag_data.suffix = tag[len(tag_directive.prefix):] emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
}
return true return true
} }
}
emitter.tag_data.suffix = tag emitter.tag_data.suffix = tag
return true return true
} }
@@ -1279,6 +1279,9 @@ func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_
for k := 0; k < w; k++ { for k := 0; k < w; k++ {
octet := value[i] octet := value[i]
i++ i++
if !put(emitter, '%') {
return false
}
c := octet >> 4 c := octet >> 4
if c < 10 { if c < 10 {

View File

@@ -2,8 +2,10 @@ package yaml
import ( import (
"reflect" "reflect"
"regexp"
"sort" "sort"
"strconv" "strconv"
"strings"
"time" "time"
) )
@@ -50,14 +52,19 @@ func (e *encoder) must(ok bool) {
if msg == "" { if msg == "" {
msg = "Unknown problem generating YAML content" msg = "Unknown problem generating YAML content"
} }
panic(msg) fail(msg)
} }
} }
func (e *encoder) marshal(tag string, in reflect.Value) { func (e *encoder) marshal(tag string, in reflect.Value) {
if !in.IsValid() {
e.nilv()
return
}
var value interface{} var value interface{}
if getter, ok := in.Interface().(Getter); ok { if getter, ok := in.Interface().(Getter); ok {
tag, value = getter.GetYAML() tag, value = getter.GetYAML()
tag = longTag(tag)
if value == nil { if value == nil {
e.nilv() e.nilv()
return return
@@ -98,7 +105,7 @@ func (e *encoder) marshal(tag string, in reflect.Value) {
case reflect.Bool: case reflect.Bool:
e.boolv(tag, in) e.boolv(tag, in)
default: default:
panic("Can't marshal type yet: " + in.Type().String()) panic("Can't marshal type: " + in.Type().String())
} }
} }
@@ -167,11 +174,46 @@ func (e *encoder) slicev(tag string, in reflect.Value) {
e.emit() e.emit()
} }
// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
//
// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
// in YAML 1.2 and by this package, but these should be marshalled quoted for
// the time being for compatibility with other parsers.
func isBase60Float(s string) (result bool) {
// Fast path.
if s == "" {
return false
}
c := s[0]
if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
return false
}
// Do the full match.
return base60float.MatchString(s)
}
// From http://yaml.org/type/float.html, except the regular expression there
// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
func (e *encoder) stringv(tag string, in reflect.Value) { func (e *encoder) stringv(tag string, in reflect.Value) {
var style yaml_scalar_style_t var style yaml_scalar_style_t
s := in.String() s := in.String()
if rtag, _ := resolve("", s); rtag != "!!str" { rtag, rs := resolve("", s)
if rtag == yaml_BINARY_TAG {
if tag == "" || tag == yaml_STR_TAG {
tag = rtag
s = rs.(string)
} else if tag == yaml_BINARY_TAG {
fail("explicitly tagged !!binary data must be base64-encoded")
} else {
fail("cannot marshal invalid UTF-8 data as " + shortTag(tag))
}
}
if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) {
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
} else if strings.Contains(s, "\n") {
style = yaml_LITERAL_SCALAR_STYLE
} else { } else {
style = yaml_PLAIN_SCALAR_STYLE style = yaml_PLAIN_SCALAR_STYLE
} }
@@ -218,9 +260,6 @@ func (e *encoder) nilv() {
func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) { func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
implicit := tag == "" implicit := tag == ""
if !implicit {
style = yaml_PLAIN_SCALAR_STYLE
}
e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
e.emit() e.emit()
} }

View File

@@ -2,12 +2,13 @@ package yaml_test
import ( import (
"fmt" "fmt"
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/gopkg.in/yaml.v1"
. "gopkg.in/check.v1"
"math" "math"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/coreos/yaml"
. "gopkg.in/check.v1"
) )
var marshalIntTest = 123 var marshalIntTest = 123
@@ -17,6 +18,9 @@ var marshalTests = []struct {
data string data string
}{ }{
{ {
nil,
"null\n",
}, {
&struct{}{}, &struct{}{},
"{}\n", "{}\n",
}, { }, {
@@ -87,7 +91,7 @@ var marshalTests = []struct {
"v:\n- A\n- B\n", "v:\n- A\n- B\n",
}, { }, {
map[string][]string{"v": []string{"A", "B\nC"}}, map[string][]string{"v": []string{"A", "B\nC"}},
"v:\n- A\n- 'B\n\n C'\n", "v:\n- A\n- |-\n B\n C\n",
}, { }, {
map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}}, map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}},
"v:\n- A\n- 1\n- B:\n - 2\n - 3\n", "v:\n- A\n- 1\n- B:\n - 2\n - 3\n",
@@ -220,11 +224,39 @@ var marshalTests = []struct {
"a: 3s\n", "a: 3s\n",
}, },
// Issue #24. // Issue #24: bug in map merging logic.
{ {
map[string]string{"a": "<foo>"}, map[string]string{"a": "<foo>"},
"a: <foo>\n", "a: <foo>\n",
}, },
// Issue #34: marshal unsupported base 60 floats quoted for compatibility
// with old YAML 1.1 parsers.
{
map[string]string{"a": "1:1"},
"a: \"1:1\"\n",
},
// Binary data.
{
map[string]string{"a": "\x00"},
"a: \"\\0\"\n",
}, {
map[string]string{"a": "\x80\x81\x82"},
"a: !!binary gIGC\n",
}, {
map[string]string{"a": strings.Repeat("\x90", 54)},
"a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
}, {
map[string]interface{}{"a": typeWithGetter{"!!str", "\x80\x81\x82"}},
"a: !!binary gIGC\n",
},
// Escaping of tags.
{
map[string]interface{}{"a": typeWithGetter{"foo!bar", 1}},
"a: !<foo%21bar> 1\n",
},
} }
func (s *S) TestMarshal(c *C) { func (s *S) TestMarshal(c *C) {
@@ -238,22 +270,31 @@ func (s *S) TestMarshal(c *C) {
var marshalErrorTests = []struct { var marshalErrorTests = []struct {
value interface{} value interface{}
error string error string
}{ panic string
{ }{{
&struct { value: &struct {
B int B int
inlineB ",inline" inlineB ",inline"
}{1, inlineB{2, inlineC{3}}}, }{1, inlineB{2, inlineC{3}}},
`Duplicated key 'b' in struct struct \{ B int; .*`, panic: `Duplicated key 'b' in struct struct \{ B int; .*`,
}, }, {
} value: typeWithGetter{"!!binary", "\x80"},
error: "YAML error: explicitly tagged !!binary data must be base64-encoded",
}, {
value: typeWithGetter{"!!float", "\x80"},
error: `YAML error: cannot marshal invalid UTF-8 data as !!float`,
}}
func (s *S) TestMarshalErrors(c *C) { func (s *S) TestMarshalErrors(c *C) {
for _, item := range marshalErrorTests { for _, item := range marshalErrorTests {
if item.panic != "" {
c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic)
} else {
_, err := yaml.Marshal(item.value) _, err := yaml.Marshal(item.value)
c.Assert(err, ErrorMatches, item.error) c.Assert(err, ErrorMatches, item.error)
} }
} }
}
var marshalTaggedIfaceTest interface{} = &struct{ A string }{"B"} var marshalTaggedIfaceTest interface{} = &struct{ A string }{"B"}

190
Godeps/_workspace/src/github.com/coreos/yaml/resolve.go generated vendored Normal file
View File

@@ -0,0 +1,190 @@
package yaml
import (
"encoding/base64"
"fmt"
"math"
"strconv"
"strings"
"unicode/utf8"
)
// TODO: merge, timestamps, base 60 floats, omap.
type resolveMapItem struct {
value interface{}
tag string
}
var resolveTable = make([]byte, 256)
var resolveMap = make(map[string]resolveMapItem)
func init() {
t := resolveTable
t[int('+')] = 'S' // Sign
t[int('-')] = 'S'
for _, c := range "0123456789" {
t[int(c)] = 'D' // Digit
}
for _, c := range "yYnNtTfFoO~" {
t[int(c)] = 'M' // In map
}
t[int('.')] = '.' // Float (potentially in map)
var resolveMapList = []struct {
v interface{}
tag string
l []string
}{
{true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}},
{true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}},
{true, yaml_BOOL_TAG, []string{"on", "On", "ON"}},
{false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}},
{false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}},
{false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}},
{nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}},
{math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}},
{math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}},
{math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}},
{math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}},
{"<<", yaml_MERGE_TAG, []string{"<<"}},
}
m := resolveMap
for _, item := range resolveMapList {
for _, s := range item.l {
m[s] = resolveMapItem{item.v, item.tag}
}
}
}
const longTagPrefix = "tag:yaml.org,2002:"
func shortTag(tag string) string {
// TODO This can easily be made faster and produce less garbage.
if strings.HasPrefix(tag, longTagPrefix) {
return "!!" + tag[len(longTagPrefix):]
}
return tag
}
func longTag(tag string) string {
if strings.HasPrefix(tag, "!!") {
return longTagPrefix + tag[2:]
}
return tag
}
func resolvableTag(tag string) bool {
switch tag {
case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG:
return true
}
return false
}
func resolve(tag string, in string) (rtag string, out interface{}) {
if !resolvableTag(tag) {
return tag, in
}
defer func() {
switch tag {
case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
return
}
fail(fmt.Sprintf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)))
}()
// Any data is accepted as a !!str or !!binary.
// Otherwise, the prefix is enough of a hint about what it might be.
hint := byte('N')
if in != "" {
hint = resolveTable[in[0]]
}
if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG {
// Handle things we can lookup in a map.
if item, ok := resolveMap[in]; ok {
return item.tag, item.value
}
// Base 60 floats are a bad idea, were dropped in YAML 1.2, and
// are purposefully unsupported here. They're still quoted on
// the way out for compatibility with other parser, though.
switch hint {
case 'M':
// We've already checked the map above.
case '.':
// Not in the map, so maybe a normal float.
floatv, err := strconv.ParseFloat(in, 64)
if err == nil {
return yaml_FLOAT_TAG, floatv
}
case 'D', 'S':
// Int, float, or timestamp.
plain := strings.Replace(in, "_", "", -1)
intv, err := strconv.ParseInt(plain, 0, 64)
if err == nil {
if intv == int64(int(intv)) {
return yaml_INT_TAG, int(intv)
} else {
return yaml_INT_TAG, intv
}
}
floatv, err := strconv.ParseFloat(plain, 64)
if err == nil {
return yaml_FLOAT_TAG, floatv
}
if strings.HasPrefix(plain, "0b") {
intv, err := strconv.ParseInt(plain[2:], 2, 64)
if err == nil {
return yaml_INT_TAG, int(intv)
}
} else if strings.HasPrefix(plain, "-0b") {
intv, err := strconv.ParseInt(plain[3:], 2, 64)
if err == nil {
return yaml_INT_TAG, -int(intv)
}
}
// XXX Handle timestamps here.
default:
panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")")
}
}
if tag == yaml_BINARY_TAG {
return yaml_BINARY_TAG, in
}
if utf8.ValidString(in) {
return yaml_STR_TAG, in
}
return yaml_BINARY_TAG, encodeBase64(in)
}
// encodeBase64 encodes s as base64 that is broken up into multiple lines
// as appropriate for the resulting length.
func encodeBase64(s string) string {
const lineLen = 70
encLen := base64.StdEncoding.EncodedLen(len(s))
lines := encLen/lineLen + 1
buf := make([]byte, encLen*2+lines)
in := buf[0:encLen]
out := buf[encLen:]
base64.StdEncoding.Encode(in, []byte(s))
k := 0
for i := 0; i < len(in); i += lineLen {
j := i + lineLen
if j > len(in) {
j = len(in)
}
k += copy(out[k:], in[i:j])
if lines > 1 {
out[k] = '\n'
k++
}
}
return string(out[:k])
}

View File

@@ -10,23 +10,20 @@ import (
"errors" "errors"
"fmt" "fmt"
"reflect" "reflect"
"runtime"
"strings" "strings"
"sync" "sync"
) )
type yamlError string
func fail(msg string) {
panic(yamlError(msg))
}
func handleErr(err *error) { func handleErr(err *error) {
if r := recover(); r != nil { if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok { if e, ok := r.(yamlError); ok {
panic(r) *err = errors.New("YAML error: " + string(e))
} else if _, ok := r.(*reflect.ValueError); ok {
panic(r)
} else if _, ok := r.(externalPanic); ok {
panic(r)
} else if s, ok := r.(string); ok {
*err = errors.New("YAML error: " + s)
} else if e, ok := r.(error); ok {
*err = e
} else { } else {
panic(r) panic(r)
} }
@@ -78,7 +75,7 @@ type Getter interface {
// F int `yaml:"a,omitempty"` // F int `yaml:"a,omitempty"`
// B int // B int
// } // }
// var T t // var t T
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) // yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
// //
// See the documentation of Marshal for the format of tags and a list of // See the documentation of Marshal for the format of tags and a list of
@@ -87,11 +84,15 @@ type Getter interface {
func Unmarshal(in []byte, out interface{}) (err error) { func Unmarshal(in []byte, out interface{}) (err error) {
defer handleErr(&err) defer handleErr(&err)
d := newDecoder() d := newDecoder()
p := newParser(in) p := newParser(in, UnmarshalMappingKeyTransform)
defer p.destroy() defer p.destroy()
node := p.parse() node := p.parse()
if node != nil { if node != nil {
d.unmarshal(node, reflect.ValueOf(out)) v := reflect.ValueOf(out)
if v.Kind() == reflect.Ptr && !v.IsNil() {
v = v.Elem()
}
d.unmarshal(node, v)
} }
return nil return nil
} }
@@ -145,6 +146,17 @@ func Marshal(in interface{}) (out []byte, err error) {
return return
} }
// UnmarshalMappingKeyTransform is a string transformation that is applied to
// each mapping key in a YAML document before it is unmarshalled. By default,
// UnmarshalMappingKeyTransform is an identity transform (no modification).
var UnmarshalMappingKeyTransform transformString = identityTransform
type transformString func(in string) (out string)
func identityTransform(in string) (out string) {
return in
}
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// Maintain a mapping of keys to structure field indexes // Maintain a mapping of keys to structure field indexes
@@ -174,12 +186,6 @@ type fieldInfo struct {
var structMap = make(map[reflect.Type]*structInfo) var structMap = make(map[reflect.Type]*structInfo)
var fieldMapMutex sync.RWMutex var fieldMapMutex sync.RWMutex
type externalPanic string
func (e externalPanic) String() string {
return string(e)
}
func getStructInfo(st reflect.Type) (*structInfo, error) { func getStructInfo(st reflect.Type) (*structInfo, error) {
fieldMapMutex.RLock() fieldMapMutex.RLock()
sinfo, found := structMap[st] sinfo, found := structMap[st]
@@ -220,8 +226,7 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
case "inline": case "inline":
inline = true inline = true
default: default:
msg := fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st) return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st))
panic(externalPanic(msg))
} }
} }
tag = fields[0] tag = fields[0]
@@ -229,6 +234,7 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
if inline { if inline {
switch field.Type.Kind() { switch field.Type.Kind() {
// TODO: Implement support for inline maps.
//case reflect.Map: //case reflect.Map:
// if inlineMap >= 0 { // if inlineMap >= 0 {
// return nil, errors.New("Multiple ,inline maps in struct " + st.String()) // return nil, errors.New("Multiple ,inline maps in struct " + st.String())
@@ -256,8 +262,8 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
fieldsList = append(fieldsList, finfo) fieldsList = append(fieldsList, finfo)
} }
default: default:
//panic("Option ,inline needs a struct value or map field") //return nil, errors.New("Option ,inline needs a struct value or map field")
panic("Option ,inline needs a struct value field") return nil, errors.New("Option ,inline needs a struct value field")
} }
continue continue
} }

View File

@@ -294,6 +294,10 @@ const (
yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
// Not in original libyaml.
yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str.
yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map.

View File

@@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@@ -0,0 +1,272 @@
/*********************************************************
* Copyright (C) 1999-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* backdoor.c --
*
* First layer of the internal communication channel between guest
* applications and vmware
*
* This is the backdoor. By using special ports of the virtual I/O space,
* and the virtual CPU registers, a guest application can send a
* synchroneous basic request to vmware, and vmware can reply to it.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "backdoor_def.h"
#include "backdoor.h"
#include "backdoorInt.h"
#if defined(BACKDOOR_DEBUG) && defined(USERLEVEL)
#if defined(__KERNEL__) || defined(_KERNEL)
#else
# include "debug.h"
#endif
# include <stdio.h>
# define BACKDOOR_LOG(args) Debug args
# define BACKDOOR_LOG_PROTO_STRUCT(x) BackdoorPrintProtoStruct((x))
# define BACKDOOR_LOG_HB_PROTO_STRUCT(x) BackdoorPrintHbProtoStruct((x))
/*
*----------------------------------------------------------------------------
*
* BackdoorPrintProtoStruct --
* BackdoorPrintHbProtoStruct --
*
* Print the contents of the specified backdoor protocol structure via
* printf.
*
* Results:
* None.
*
* Side effects:
* Output to stdout.
*
*----------------------------------------------------------------------------
*/
void
BackdoorPrintProtoStruct(Backdoor_proto *myBp)
{
Debug("magic 0x%08x, command %d, size %"FMTSZ"u, port %d\n",
myBp->in.ax.word, myBp->in.cx.halfs.low,
myBp->in.size, myBp->in.dx.halfs.low);
#ifndef VM_X86_64
Debug("ax %#x, "
"bx %#x, "
"cx %#x, "
"dx %#x, "
"si %#x, "
"di %#x\n",
myBp->out.ax.word,
myBp->out.bx.word,
myBp->out.cx.word,
myBp->out.dx.word,
myBp->out.si.word,
myBp->out.di.word);
#else
Debug("ax %#"FMT64"x, "
"bx %#"FMT64"x, "
"cx %#"FMT64"x, "
"dx %#"FMT64"x, "
"si %#"FMT64"x, "
"di %#"FMT64"x\n",
myBp->out.ax.quad,
myBp->out.bx.quad,
myBp->out.cx.quad,
myBp->out.dx.quad,
myBp->out.si.quad,
myBp->out.di.quad);
#endif
}
void
BackdoorPrintHbProtoStruct(Backdoor_proto_hb *myBp)
{
Debug("magic 0x%08x, command %d, size %"FMTSZ"u, port %d, "
"srcAddr %"FMTSZ"u, dstAddr %"FMTSZ"u\n",
myBp->in.ax.word, myBp->in.bx.halfs.low, myBp->in.size,
myBp->in.dx.halfs.low, myBp->in.srcAddr, myBp->in.dstAddr);
#ifndef VM_X86_64
Debug("ax %#x, "
"bx %#x, "
"cx %#x, "
"dx %#x, "
"si %#x, "
"di %#x, "
"bp %#x\n",
myBp->out.ax.word,
myBp->out.bx.word,
myBp->out.cx.word,
myBp->out.dx.word,
myBp->out.si.word,
myBp->out.di.word,
myBp->out.bp.word);
#else
Debug("ax %#"FMT64"x, "
"bx %#"FMT64"x, "
"cx %#"FMT64"x, "
"dx %#"FMT64"x, "
"si %#"FMT64"x, "
"di %#"FMT64"x, "
"bp %#"FMT64"x\n",
myBp->out.ax.quad,
myBp->out.bx.quad,
myBp->out.cx.quad,
myBp->out.dx.quad,
myBp->out.si.quad,
myBp->out.di.quad,
myBp->out.bp.quad);
#endif
}
#else
# define BACKDOOR_LOG(args)
# define BACKDOOR_LOG_PROTO_STRUCT(x)
# define BACKDOOR_LOG_HB_PROTO_STRUCT(x)
#endif
/*
*-----------------------------------------------------------------------------
*
* Backdoor --
*
* Send a low-bandwidth basic request (16 bytes) to vmware, and return its
* reply (24 bytes).
*
* Result:
* None
*
* Side-effects:
* None
*
*-----------------------------------------------------------------------------
*/
void
Backdoor(Backdoor_proto *myBp) // IN/OUT
{
ASSERT(myBp);
myBp->in.ax.word = BDOOR_MAGIC;
myBp->in.dx.halfs.low = BDOOR_PORT;
BACKDOOR_LOG(("Backdoor: before "));
BACKDOOR_LOG_PROTO_STRUCT(myBp);
Backdoor_InOut(myBp);
BACKDOOR_LOG(("Backdoor: after "));
BACKDOOR_LOG_PROTO_STRUCT(myBp);
}
/*
*-----------------------------------------------------------------------------
*
* Backdoor_HbOut --
*
* Send a high-bandwidth basic request to vmware, and return its
* reply.
*
* Result:
* The host-side response is returned via the IN/OUT parameter.
*
* Side-effects:
* Pokes the high-bandwidth backdoor.
*
*-----------------------------------------------------------------------------
*/
void
Backdoor_HbOut(Backdoor_proto_hb *myBp) // IN/OUT
{
ASSERT(myBp);
myBp->in.ax.word = BDOOR_MAGIC;
myBp->in.dx.halfs.low = BDOORHB_PORT;
BACKDOOR_LOG(("Backdoor_HbOut: before "));
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
BackdoorHbOut(myBp);
BACKDOOR_LOG(("Backdoor_HbOut: after "));
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
}
/*
*-----------------------------------------------------------------------------
*
* Backdoor_HbIn --
*
* Send a basic request to vmware, and return its high-bandwidth
* reply
*
* Result:
* Host-side response returned via the IN/OUT parameter.
*
* Side-effects:
* Pokes the high-bandwidth backdoor.
*
*-----------------------------------------------------------------------------
*/
void
Backdoor_HbIn(Backdoor_proto_hb *myBp) // IN/OUT
{
ASSERT(myBp);
myBp->in.ax.word = BDOOR_MAGIC;
myBp->in.dx.halfs.low = BDOORHB_PORT;
BACKDOOR_LOG(("Backdoor_HbIn: before "));
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
BackdoorHbIn(myBp);
BACKDOOR_LOG(("Backdoor_HbIn: after "));
BACKDOOR_LOG_HB_PROTO_STRUCT(myBp);
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,235 @@
/*********************************************************
* Copyright (C) 2005-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* backdoorGcc32.c --
*
* Implements the real work for guest-side backdoor for GCC, 32-bit
* target (supports inline ASM, GAS syntax). The asm sections are marked
* volatile since vmware can change the registers content without the
* compiler knowing it.
*
* XXX
* I tried to write this more cleanly, but:
* - There is no way to specify an "ebp" constraint
* - "ebp" is ignored when specified as cloberred register
* - gas barfs when there is more than 10 operands
* - gas 2.7.2.3, depending on the order of the operands, can
* mis-assemble without any warning
* --hpreg
*
* Note that the problems with gas noted above might longer be relevant
* now that we've upgraded most of our compiler versions.
* --rrdharan
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "backdoor.h"
#include "backdoorInt.h"
/*
*----------------------------------------------------------------------------
*
* Backdoor_InOut --
*
* Send a low-bandwidth basic request (16 bytes) to vmware, and return its
* reply (24 bytes).
*
* Results:
* Host-side response returned in bp IN/OUT parameter.
*
* Side effects:
* Pokes the backdoor.
*
*----------------------------------------------------------------------------
*/
void
Backdoor_InOut(Backdoor_proto *myBp) // IN/OUT
{
uint32 dummy;
__asm__ __volatile__(
#ifdef __PIC__
"pushl %%ebx" "\n\t"
#endif
"pushl %%eax" "\n\t"
"movl 20(%%eax), %%edi" "\n\t"
"movl 16(%%eax), %%esi" "\n\t"
"movl 12(%%eax), %%edx" "\n\t"
"movl 8(%%eax), %%ecx" "\n\t"
"movl 4(%%eax), %%ebx" "\n\t"
"movl (%%eax), %%eax" "\n\t"
"inl %%dx, %%eax" "\n\t"
"xchgl %%eax, (%%esp)" "\n\t"
"movl %%edi, 20(%%eax)" "\n\t"
"movl %%esi, 16(%%eax)" "\n\t"
"movl %%edx, 12(%%eax)" "\n\t"
"movl %%ecx, 8(%%eax)" "\n\t"
"movl %%ebx, 4(%%eax)" "\n\t"
"popl (%%eax)" "\n\t"
#ifdef __PIC__
"popl %%ebx" "\n\t"
#endif
: "=a" (dummy)
: "0" (myBp)
/*
* vmware can modify the whole VM state without the compiler knowing
* it. So far it does not modify EFLAGS. --hpreg
*/
:
#ifndef __PIC__
"ebx",
#endif
"ecx", "edx", "esi", "edi", "memory"
);
}
/*
*-----------------------------------------------------------------------------
*
* BackdoorHbIn --
* BackdoorHbOut --
*
* Send a high-bandwidth basic request to vmware, and return its
* reply.
*
* Results:
* Host-side response returned in bp IN/OUT parameter.
*
* Side-effects:
* Pokes the high-bandwidth backdoor port.
*
*-----------------------------------------------------------------------------
*/
void
BackdoorHbIn(Backdoor_proto_hb *myBp) // IN/OUT
{
uint32 dummy;
__asm__ __volatile__(
#ifdef __PIC__
"pushl %%ebx" "\n\t"
#endif
"pushl %%ebp" "\n\t"
"pushl %%eax" "\n\t"
"movl 24(%%eax), %%ebp" "\n\t"
"movl 20(%%eax), %%edi" "\n\t"
"movl 16(%%eax), %%esi" "\n\t"
"movl 12(%%eax), %%edx" "\n\t"
"movl 8(%%eax), %%ecx" "\n\t"
"movl 4(%%eax), %%ebx" "\n\t"
"movl (%%eax), %%eax" "\n\t"
"cld" "\n\t"
"rep; insb" "\n\t"
"xchgl %%eax, (%%esp)" "\n\t"
"movl %%ebp, 24(%%eax)" "\n\t"
"movl %%edi, 20(%%eax)" "\n\t"
"movl %%esi, 16(%%eax)" "\n\t"
"movl %%edx, 12(%%eax)" "\n\t"
"movl %%ecx, 8(%%eax)" "\n\t"
"movl %%ebx, 4(%%eax)" "\n\t"
"popl (%%eax)" "\n\t"
"popl %%ebp" "\n\t"
#ifdef __PIC__
"popl %%ebx" "\n\t"
#endif
: "=a" (dummy)
: "0" (myBp)
/*
* vmware can modify the whole VM state without the compiler knowing
* it. --hpreg
*/
:
#ifndef __PIC__
"ebx",
#endif
"ecx", "edx", "esi", "edi", "memory", "cc"
);
}
void
BackdoorHbOut(Backdoor_proto_hb *myBp) // IN/OUT
{
uint32 dummy;
__asm__ __volatile__(
#ifdef __PIC__
"pushl %%ebx" "\n\t"
#endif
"pushl %%ebp" "\n\t"
"pushl %%eax" "\n\t"
"movl 24(%%eax), %%ebp" "\n\t"
"movl 20(%%eax), %%edi" "\n\t"
"movl 16(%%eax), %%esi" "\n\t"
"movl 12(%%eax), %%edx" "\n\t"
"movl 8(%%eax), %%ecx" "\n\t"
"movl 4(%%eax), %%ebx" "\n\t"
"movl (%%eax), %%eax" "\n\t"
"cld" "\n\t"
"rep; outsb" "\n\t"
"xchgl %%eax, (%%esp)" "\n\t"
"movl %%ebp, 24(%%eax)" "\n\t"
"movl %%edi, 20(%%eax)" "\n\t"
"movl %%esi, 16(%%eax)" "\n\t"
"movl %%edx, 12(%%eax)" "\n\t"
"movl %%ecx, 8(%%eax)" "\n\t"
"movl %%ebx, 4(%%eax)" "\n\t"
"popl (%%eax)" "\n\t"
"popl %%ebp" "\n\t"
#ifdef __PIC__
"popl %%ebx" "\n\t"
#endif
: "=a" (dummy)
: "0" (myBp)
:
#ifndef __PIC__
"ebx",
#endif
"ecx", "edx", "esi", "edi", "memory", "cc"
);
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,243 @@
/*********************************************************
* Copyright (C) 2005-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* backdoorGcc64.c --
*
* Implements the real work for guest-side backdoor for GCC, 64-bit
* target (supports inline ASM, GAS syntax). The asm sections are marked
* volatile since vmware can change the registers content without the
* compiler knowing it.
*
* See backdoorGCC32.c (from which this code was mostly copied) for
* details on why the ASM is written this way. Also note that it might be
* possible to write the asm blocks using the symbolic operand specifiers
* in such a way that the same asm would generate correct code for both
* 32-bit and 64-bit targets, but I'm too lazy to figure it all out.
* --rrdharan
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "backdoor.h"
#include "backdoorInt.h"
/*
*----------------------------------------------------------------------------
*
* Backdoor_InOut --
*
* Send a low-bandwidth basic request (16 bytes) to vmware, and return its
* reply (24 bytes).
*
* Results:
* Host-side response returned in bp IN/OUT parameter.
*
* Side effects:
* Pokes the backdoor.
*
*----------------------------------------------------------------------------
*/
void
Backdoor_InOut(Backdoor_proto *myBp) // IN/OUT
{
uint64 dummy;
__asm__ __volatile__(
#ifdef __APPLE__
/*
* Save %rbx on the stack because the Mac OS GCC doesn't want us to
* clobber it - it erroneously thinks %rbx is the PIC register.
* (Radar bug 7304232)
*/
"pushq %%rbx" "\n\t"
#endif
"pushq %%rax" "\n\t"
"movq 40(%%rax), %%rdi" "\n\t"
"movq 32(%%rax), %%rsi" "\n\t"
"movq 24(%%rax), %%rdx" "\n\t"
"movq 16(%%rax), %%rcx" "\n\t"
"movq 8(%%rax), %%rbx" "\n\t"
"movq (%%rax), %%rax" "\n\t"
"inl %%dx, %%eax" "\n\t" /* NB: There is no inq instruction */
"xchgq %%rax, (%%rsp)" "\n\t"
"movq %%rdi, 40(%%rax)" "\n\t"
"movq %%rsi, 32(%%rax)" "\n\t"
"movq %%rdx, 24(%%rax)" "\n\t"
"movq %%rcx, 16(%%rax)" "\n\t"
"movq %%rbx, 8(%%rax)" "\n\t"
"popq (%%rax)" "\n\t"
#ifdef __APPLE__
"popq %%rbx" "\n\t"
#endif
: "=a" (dummy)
: "0" (myBp)
/*
* vmware can modify the whole VM state without the compiler knowing
* it. So far it does not modify EFLAGS. --hpreg
*/
:
#ifndef __APPLE__
/* %rbx is unchanged at the end of the function on Mac OS. */
"rbx",
#endif
"rcx", "rdx", "rsi", "rdi", "memory"
);
}
/*
*-----------------------------------------------------------------------------
*
* BackdoorHbIn --
* BackdoorHbOut --
*
* Send a high-bandwidth basic request to vmware, and return its
* reply.
*
* Results:
* Host-side response returned in bp IN/OUT parameter.
*
* Side-effects:
* Pokes the high-bandwidth backdoor port.
*
*-----------------------------------------------------------------------------
*/
void
BackdoorHbIn(Backdoor_proto_hb *myBp) // IN/OUT
{
uint64 dummy;
__asm__ __volatile__(
"pushq %%rbp" "\n\t"
#ifdef __APPLE__
/*
* Save %rbx on the stack because the Mac OS GCC doesn't want us to
* clobber it - it erroneously thinks %rbx is the PIC register.
* (Radar bug 7304232)
*/
"pushq %%rbx" "\n\t"
#endif
"pushq %%rax" "\n\t"
"movq 48(%%rax), %%rbp" "\n\t"
"movq 40(%%rax), %%rdi" "\n\t"
"movq 32(%%rax), %%rsi" "\n\t"
"movq 24(%%rax), %%rdx" "\n\t"
"movq 16(%%rax), %%rcx" "\n\t"
"movq 8(%%rax), %%rbx" "\n\t"
"movq (%%rax), %%rax" "\n\t"
"cld" "\n\t"
"rep; insb" "\n\t"
"xchgq %%rax, (%%rsp)" "\n\t"
"movq %%rbp, 48(%%rax)" "\n\t"
"movq %%rdi, 40(%%rax)" "\n\t"
"movq %%rsi, 32(%%rax)" "\n\t"
"movq %%rdx, 24(%%rax)" "\n\t"
"movq %%rcx, 16(%%rax)" "\n\t"
"movq %%rbx, 8(%%rax)" "\n\t"
"popq (%%rax)" "\n\t"
#ifdef __APPLE__
"popq %%rbx" "\n\t"
#endif
"popq %%rbp"
: "=a" (dummy)
: "0" (myBp)
/*
* vmware can modify the whole VM state without the compiler knowing
* it. --hpreg
*/
:
#ifndef __APPLE__
/* %rbx is unchanged at the end of the function on Mac OS. */
"rbx",
#endif
"rcx", "rdx", "rsi", "rdi", "memory", "cc"
);
}
void
BackdoorHbOut(Backdoor_proto_hb *myBp) // IN/OUT
{
uint64 dummy;
__asm__ __volatile__(
"pushq %%rbp" "\n\t"
#ifdef __APPLE__
/*
* Save %rbx on the stack because the Mac OS GCC doesn't want us to
* clobber it - it erroneously thinks %rbx is the PIC register.
* (Radar bug 7304232)
*/
"pushq %%rbx" "\n\t"
#endif
"pushq %%rax" "\n\t"
"movq 48(%%rax), %%rbp" "\n\t"
"movq 40(%%rax), %%rdi" "\n\t"
"movq 32(%%rax), %%rsi" "\n\t"
"movq 24(%%rax), %%rdx" "\n\t"
"movq 16(%%rax), %%rcx" "\n\t"
"movq 8(%%rax), %%rbx" "\n\t"
"movq (%%rax), %%rax" "\n\t"
"cld" "\n\t"
"rep; outsb" "\n\t"
"xchgq %%rax, (%%rsp)" "\n\t"
"movq %%rbp, 48(%%rax)" "\n\t"
"movq %%rdi, 40(%%rax)" "\n\t"
"movq %%rsi, 32(%%rax)" "\n\t"
"movq %%rdx, 24(%%rax)" "\n\t"
"movq %%rcx, 16(%%rax)" "\n\t"
"movq %%rbx, 8(%%rax)" "\n\t"
"popq (%%rax)" "\n\t"
#ifdef __APPLE__
"popq %%rbx" "\n\t"
#endif
"popq %%rbp"
: "=a" (dummy)
: "0" (myBp)
:
#ifndef __APPLE__
/* %rbx is unchanged at the end of the function on Mac OS. */
"rbx",
#endif
"rcx", "rdx", "rsi", "rdi", "memory", "cc"
);
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,60 @@
package bridge
/*
#cgo CFLAGS: -I../include
#include <stdlib.h>
#include "message.h"
#include "vmcheck.h"
void Warning(const char *fmt, ...) {}
void Debug(const char *fmt, ...) {}
void Panic(const char *fmt, ...) {}
void Log(const char *fmt, ...) {}
*/
import "C"
import "unsafe"
// MessageChannel provides a channel to pass information from/to the hypervisor
type MessageChannel *C.struct_Message_Channel
// MessageOpen creates a new MessageChannel
func MessageOpen(proto uint32) MessageChannel {
return C.Message_Open(C.uint32(proto))
}
// MessageClose closes a MessageChannel
func MessageClose(c MessageChannel) bool {
status := C.Message_Close(c)
return status != 0
}
// MessageSend sends a request through a MessageChannel
func MessageSend(c MessageChannel, request []byte) bool {
buffer := (*C.uchar)(unsafe.Pointer(&request[0]))
status := C.Message_Send(c, buffer, (C.size_t)(C.int(len(request))))
return status != 0
}
// MessageReceive receives a response through a MessageChannel
func MessageReceive(c MessageChannel) ([]byte, bool) {
var reply *C.uchar
var replyLen C.size_t
defer C.free(unsafe.Pointer(reply))
status := C.Message_Receive(c, &reply, &replyLen)
res := C.GoBytes(unsafe.Pointer(reply), (C.int)(replyLen))
return res, status != 0
}
// VMCheckIsVirtualWorld checks if current code is running in a VMware virtual machine
func VMCheckIsVirtualWorld() bool {
return C.VmCheck_IsVirtualWorld() != 0
}
// VMCheckGetVersion returns the identifiers of the current hypervisor
func VMCheckGetVersion() (uint32, uint32) {
var version C.uint32
var typ C.uint32
C.VmCheck_GetVersion(&version, &typ)
return uint32(version), uint32(typ)
}

View File

@@ -0,0 +1,439 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* dynbuf.c --
*
* Dynamic buffers --hpreg
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vmware.h"
#include "dynbuf.h"
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Init --
*
* Dynamic buffer constructor --hpreg
*
* Results:
* None
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
void
DynBuf_Init(DynBuf *b) // OUT:
{
ASSERT(b);
b->data = NULL;
b->size = 0;
b->allocated = 0;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Destroy --
*
* Dynamic buffer destructor --hpreg
*
* Results:
* None
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
void
DynBuf_Destroy(DynBuf *b) // IN/OUT:
{
ASSERT(b);
free(b->data);
DynBuf_Init(b);
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_AllocGet --
*
* Retrieve a pointer to the data contained in a dynamic buffer. Return
* a copy of that data.
*
* Results:
* The pointer to the data. NULL on out of memory failure.
*
* Side effects:
* Allocates memory.
*
*-----------------------------------------------------------------------------
*/
void *
DynBuf_AllocGet(DynBuf const *b) // IN
{
void *new_data;
ASSERT(b);
new_data = malloc(b->size);
if (new_data) {
memcpy(new_data, b->data, b->size);
}
return new_data;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Attach --
*
* Grants ownership of the specified buffer to the DynBuf
* object. If there is an existing buffer, it is freed.
*
* Results:
* None.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
void
DynBuf_Attach(DynBuf *b, // IN
size_t size, // IN
void *data) // IN
{
ASSERT(b);
ASSERT((size == 0) == (data == NULL));
free(b->data);
b->data = data;
b->size = b->allocated = size;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Detach --
*
* Releases ownership of the buffer stored in the DynBuf object,
* and returns a pointer to it.
*
* Results:
* The pointer to the data.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
void *
DynBuf_Detach(DynBuf *b) // IN
{
void *data;
ASSERT(b);
data = b->data;
b->data = NULL;
b->allocated = 0;
return data;
}
/*
*-----------------------------------------------------------------------------
*
* DynBufRealloc --
*
* Reallocate a dynamic buffer --hpreg
*
* Results:
* TRUE on success
* FALSE on failure (not enough memory)
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static Bool
DynBufRealloc(DynBuf *b, // IN:
size_t newAllocated) // IN:
{
void *new_data;
ASSERT(b);
new_data = realloc(b->data, newAllocated);
if (new_data == NULL && newAllocated) {
/* Not enough memory */
return FALSE;
}
b->data = new_data;
b->allocated = newAllocated;
return TRUE;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Enlarge --
*
* Enlarge a dynamic buffer. The resulting dynamic buffer is guaranteed to
* be larger than the one you passed, and at least 'minSize' bytes
* large --hpreg
*
* Results:
* TRUE on success
* FALSE on failure (not enough memory)
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
DynBuf_Enlarge(DynBuf *b, // IN:
size_t minSize) // IN:
{
size_t newAllocated;
ASSERT(b);
newAllocated = b->allocated
?
#if defined(DYNBUF_DEBUG)
b->allocated + 1
#else
/*
* Double the previously allocated size if it is less
* than 256KB; otherwise grow it linearly by 256KB
*/
(b->allocated < 256 * 1024 ? b->allocated * 2
: b->allocated + 256 * 1024)
#endif
:
#if defined(DYNBUF_DEBUG)
1
#else
/*
* Initial size: 1 KB. Most buffers are smaller than
* that --hpreg
*/
1 << 10
#endif
;
if (minSize > newAllocated) {
newAllocated = minSize;
}
/*
* Prevent integer overflow. We can use this form of checking specifically
* because a multiple by 2 is used (in the worst case). This type of
* checking does not work in the general case.
*/
if (newAllocated < b->allocated) {
return FALSE;
}
return DynBufRealloc(b, newAllocated);
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Append --
*
* Append data at the end of a dynamic buffer. 'size' is the size of the
* data. If it is <= 0, no operation is performed --hpreg
*
* Results:
* TRUE on success
* FALSE on failure (not enough memory)
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
DynBuf_Append(DynBuf *b, // IN
void const *data, // IN
size_t size) // IN
{
size_t new_size;
ASSERT(b);
if (size <= 0) {
return TRUE;
}
ASSERT(data);
new_size = b->size + size;
if (new_size < b->size) { // Prevent integer overflow
return FALSE;
}
if (new_size > b->allocated) {
/* Not enough room */
if (DynBuf_Enlarge(b, new_size) == FALSE) {
return FALSE;
}
}
memcpy(b->data + b->size, data, size);
b->size = new_size;
return TRUE;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_SafeInternalAppend --
*
* Append data at the end of a dynamic buffer. Memory allocation failure
* are handled the same way as Util_SafeMalloc, that is to say, with a
* Panic.
*
* Results:
* None
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
void
DynBuf_SafeInternalAppend(DynBuf *b, // IN
void const *data, // IN
size_t size, // IN
char const *file, // IN
unsigned int lineno) // IN
{
if (!DynBuf_Append(b, data, size)) {
Panic("Unrecoverable memory allocation failure at %s:%u\n",
file, lineno);
}
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Trim --
*
* Reallocate a dynamic buffer to the exact size it occupies --hpreg
*
* Results:
* TRUE on success
* FALSE on failure (not enough memory)
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
DynBuf_Trim(DynBuf *b) // IN
{
ASSERT(b);
return DynBufRealloc(b, b->size);
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Copy --
*
* Copies all data and metadata from src dynbuff to dest dynbuf.
*
* Dest should be an initialized DynBuf of alloced length zero
* to prevent memory leaks.
*
* Results:
* TRUE on success, FALSE on failure.
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
DynBuf_Copy(DynBuf *src, // IN
DynBuf *dest) // OUT
{
ASSERT(src);
ASSERT(dest);
ASSERT(!dest->data);
dest->data = malloc(src->allocated);
if (dest->data == NULL) {
return FALSE;
}
dest->size = src->size;
dest->allocated = src->allocated;
memcpy(dest->data, src->data, src->size);
return TRUE;
}

View File

@@ -0,0 +1,336 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* hostinfo.c --
*
* Platform-independent code that calls into hostinfo<OS>-specific
* code.
*/
#include "vmware.h"
#include <string.h>
#if defined(__i386__) || defined(__x86_64__)
#include "cpuid_info.h"
#endif
#include "hostinfo.h"
#include "hostinfoInt.h"
#include "util.h"
/* #include "str.h" */
#include <stdio.h>
#define Str_Sprintf snprintf
#include "dynbuf.h"
#include "backdoor_def.h"
/*
* #define LOGLEVEL_MODULE hostinfo
* #include "loglevel_user.h"
*/
#define LGPFX "HOSTINFO:"
/*
* HostinfoOSData caches its returned value.
*/
volatile Bool HostinfoOSNameCacheValid = FALSE;
char HostinfoCachedOSName[MAX_OS_NAME_LEN];
char HostinfoCachedOSFullName[MAX_OS_FULLNAME_LEN];
#if defined(__i386__) || defined(__x86_64__)
/*
*-----------------------------------------------------------------------------
*
* HostInfoGetCpuidStrSection --
*
* Append a section (either low or high) of CPUID as a string in DynBuf.
* E.g.
* 00000000:00000005756E65476C65746E49656E69-
* 00000001:00000F4A000208000000649DBFEBFBFF-
* or
* 80000000:80000008000000000000000000000000-
* 80000001:00000000000000000000000120100000-
* 80000008:00003024000000000000000000000000-
*
* The returned eax of args[0] is used to determine the upper bound for
* the following input arguments. And the input args should be in
* ascending order.
*
* Results:
* None. The string will be appended in buf.
*
* Side effect:
* None
*
*-----------------------------------------------------------------------------
*/
static void
HostInfoGetCpuidStrSection(const uint32 args[], // IN: input eax arguments
const size_t args_size, // IN: size of the argument array
DynBuf *buf) // IN/OUT: result string in DynBuf
{
static const char format[] = "%08X:%08X%08X%08X%08X-";
CPUIDRegs reg;
uint32 max_arg;
char temp[64];
int i;
__GET_CPUID(args[0], &reg);
max_arg = reg.eax;
if (max_arg < args[0]) {
Warning(LGPFX" No CPUID information available. Based = %08X.\n",
args[0]);
return;
}
DynBuf_Append(buf, temp,
Str_Sprintf(temp, sizeof temp, format, args[0], reg.eax,
reg.ebx, reg.ecx, reg.edx));
for (i = 1; i < args_size && args[i] <= max_arg; i++) {
ASSERT(args[i] > args[i - 1]); // Ascending order.
__GET_CPUID(args[i], &reg);
DynBuf_Append(buf, temp,
Str_Sprintf(temp, sizeof temp, format, args[i], reg.eax,
reg.ebx, reg.ecx, reg.edx));
}
}
/*
*-----------------------------------------------------------------------------
*
* Hostinfo_GetCpuidStr --
*
* Get the basic and extended CPUID as a string. E.g.
* 00000000:00000005756E65476C65746E49656E69-
* 00000001:00000F4A000208000000649DBFEBFBFF-
* 80000000:80000008000000000000000000000000-
* 80000001:00000000000000000000000120100000-
* 80000008:00003024000000000000000000000000
*
* If the extended CPUID is not available, only returns the basic CPUID.
*
* Results:
* The CPUID string if the processor supports the CPUID instruction and
* this is a processor we recognize. It should never fail, since it
* would at least return leaf 0. Caller needs to free the returned string.
*
* Side effect:
* None
*
*-----------------------------------------------------------------------------
*/
char *
Hostinfo_GetCpuidStr(void)
{
static const uint32 basic_args[] = {0x0, 0x1, 0xa};
static const uint32 extended_args[] = {0x80000000, 0x80000001, 0x80000008};
DynBuf buf;
char *result;
DynBuf_Init(&buf);
HostInfoGetCpuidStrSection(basic_args, ARRAYSIZE(basic_args), &buf);
HostInfoGetCpuidStrSection(extended_args, ARRAYSIZE(extended_args), &buf);
// Trim buffer and set NULL character to replace last '-'.
DynBuf_Trim(&buf);
result = (char*)DynBuf_Get(&buf);
ASSERT(result && result[0]); // We should at least get result from eax = 0x0.
result[DynBuf_GetSize(&buf) - 1] = '\0';
return DynBuf_Detach(&buf);
}
#endif // defined(__i386__) || defined(__x86_64__)
/*
*-----------------------------------------------------------------------------
*
* Hostinfo_GetCpuid --
*
* Get cpuid information for a CPU. Which CPU the information is for
* depends on the OS scheduler. We are assuming that all CPUs in
* the system have identical numbers of cores and threads.
*
* Results:
* TRUE if the processor supports the cpuid instruction and this
* is a process we recognize, FALSE otherwise.
*
* Side effect:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
Hostinfo_GetCpuid(HostinfoCpuIdInfo *info) // OUT
{
#if defined(__i386__) || defined(__x86_64__)
CPUIDSummary cpuid;
CPUIDRegs id0;
/*
* Can't do cpuid = {0} as an initializer above because gcc throws
* some idiotic warning.
*/
memset(&cpuid, 0, sizeof(cpuid));
/*
* Get basic and extended CPUID info.
*/
__GET_CPUID(0, &id0);
cpuid.id0.numEntries = id0.eax;
if (0 == cpuid.id0.numEntries) {
Warning(LGPFX" No CPUID information available.\n");
return FALSE;
}
*(uint32*)(cpuid.id0.name + 0) = id0.ebx;
*(uint32*)(cpuid.id0.name + 4) = id0.edx;
*(uint32*)(cpuid.id0.name + 8) = id0.ecx;
*(uint32*)(cpuid.id0.name + 12) = 0;
__GET_CPUID(1, (CPUIDRegs*)&cpuid.id1);
__GET_CPUID(0xa, (CPUIDRegs*)&cpuid.ida);
__GET_CPUID(0x80000000, (CPUIDRegs*)&cpuid.id80);
__GET_CPUID(0x80000001, (CPUIDRegs*)&cpuid.id81);
__GET_CPUID(0x80000008, (CPUIDRegs*)&cpuid.id88);
/*
* Calculate vendor information.
*/
if (0 == strcmp(cpuid.id0.name, CPUID_INTEL_VENDOR_STRING_FIXED)) {
info->vendor = CPUID_VENDOR_INTEL;
} else if (strcmp(cpuid.id0.name, CPUID_AMD_VENDOR_STRING_FIXED) == 0) {
info->vendor = CPUID_VENDOR_AMD;
} else {
info->vendor = CPUID_VENDOR_UNKNOWN;
}
/*
* Pull out versioning and feature information.
*/
info->version = cpuid.id1.version;
info->family = CPUID_GET(1, EAX, FAMILY, cpuid.id1.version);
info->model = CPUID_GET(1, EAX, MODEL, cpuid.id1.version);
info->stepping = CPUID_GET(1, EAX, STEPPING, cpuid.id1.version);
info->type = (cpuid.id1.version >> 12) & 0x0003;
info->extfeatures = cpuid.id1.ecxFeatures;
info->features = cpuid.id1.edxFeatures;
return TRUE;
#else // defined(__i386__) || defined(__x86_64__)
return FALSE;
#endif // defined(__i386__) || defined(__x86_64__)
}
/*
*-----------------------------------------------------------------------------
*
* Hostinfo_GetOSName --
*
* Query the operating system and build a string to identify it.
*
* Examples:
* Windows: <OS NAME> <SERVICE PACK> (Build <BUILD_NUMBER>)
* example: Windows XP Professional Service Pack 2 (Build 2600)
*
* Linux: <OS NAME> <OS RELEASE> <SPECIFIC_DISTRO_INFO>
* example: Linux 2.4.18-3 Red Hat Linux release 7.3 (Valhalla)
*
* Mac OS: <OS NAME> <OS VERSION> (<BUILD VERSION>) <KERNEL NAME> <KERNEL RELEASE>
* example: Mac OS X 10.8.5 (12F45) Darwin 12.5.0
*
* Return value:
* NULL Unable to obtain the OS name.
* !NULL The OS name. The caller is responsible for freeing it.
*
* Side effects:
* Memory is allocated.
*
*-----------------------------------------------------------------------------
*/
/*
* char *
* Hostinfo_GetOSName(void)
* {
* char *name;
* Bool data = HostinfoOSNameCacheValid ? TRUE : HostinfoOSData();
*
* if (data) {
* name = Util_SafeStrdup(HostinfoCachedOSFullName);
* } else {
* name = NULL;
* }
*
* return name;
* }
*/
/*
*-----------------------------------------------------------------------------
*
* Hostinfo_GetOSGuestString --
*
* Query the operating system and build a string to identify it. The
* returned string is the same as you'd see in a VM's .vmx file.
*
* Return value:
* NULL Unable to obtain the OS name.
* !NULL The OS name. The caller is responsible for freeing it.
*
* Side effects:
* Memory is allocated.
*
*-----------------------------------------------------------------------------
*/
/*
* char *
* Hostinfo_GetOSGuestString(void)
* {
* char *name;
* Bool data = HostinfoOSNameCacheValid ? TRUE : HostinfoOSData();
*
* if (data) {
* name = Util_SafeStrdup(HostinfoCachedOSName);
* } else {
* name = NULL;
* }
*
* return name;
* }
*/

View File

@@ -0,0 +1,686 @@
/*********************************************************
* Copyright (C) 2011-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* hostinfoHV.c --
*
* Code to detect different hypervisors and features.
*/
#include <string.h>
#include "vmware.h"
#if defined(__i386__) || defined(__x86_64__)
# include "cpuid_info.h"
# include "backdoor_def.h"
# include "backdoor_types.h"
#endif
#include "hostinfo.h"
#include "util.h"
#define LGPFX "HOSTINFO:"
/*
* #define LOGLEVEL_MODULE hostinfo
* #include "loglevel_user.h"
*/
/*
*----------------------------------------------------------------------
*
* Hostinfo_HypervisorCPUIDSig --
*
* Get the hypervisor signature string from CPUID.
*
* Results:
* Unqualified 16 byte nul-terminated hypervisor string
* String may contain garbage and caller must free
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
char *
Hostinfo_HypervisorCPUIDSig(void)
{
uint32 *name = NULL;
#if defined(__i386__) || defined(__x86_64__)
CPUIDRegs regs;
__GET_CPUID(1, &regs);
if (!CPUID_ISSET(1, ECX, HYPERVISOR, regs.ecx)) {
return NULL;
}
regs.ebx = 0;
regs.ecx = 0;
regs.edx = 0;
__GET_CPUID(0x40000000, &regs);
if (regs.eax < 0x40000000) {
Log(LGPFX" CPUID hypervisor bit is set, but no "
"hypervisor vendor signature is present\n");
}
name = Util_SafeMalloc(4 * sizeof *name);
name[0] = regs.ebx;
name[1] = regs.ecx;
name[2] = regs.edx;
name[3] = 0;
#endif // defined(__i386__) || defined(__x86_64__)
return (char *)name;
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_TouchXen --
*
* Check for Xen.
*
* Official way is to call Hostinfo_HypervisorCPUIDSig(), which
* returns a hypervisor string. This is a secondary check
* that guards against a backdoor failure. See PR156185,
* http://xenbits.xensource.com/xen-unstable.hg?file/6a383beedf83/tools/misc/xen-detect.c
* (Canonical way is /proc/xen, but CPUID is better).
*
* Results:
* TRUE if we are running in a Xen dom0 or domU.
* Linux:
* Illegal instruction exception on real hardware.
* Obscure Xen implementations might return FALSE.
* Windows:
* FALSE on real hardware.
*
* Side effects:
* Linux: Will raise exception on native hardware.
* Windows: None.
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_TouchXen(void)
{
#if defined(linux) && (defined(__i386__) || defined(__x86_64__))
#define XEN_CPUID 0x40000000
CPUIDRegs regs;
uint32 name[4];
/*
* PV mode: ud2a "xen" cpuid (faults on native hardware).
* (Only Linux can run PV, so skip others here).
* Since PV cannot trap CPUID, this is a Xen hook.
*/
regs.eax = XEN_CPUID;
__asm__ __volatile__(
"xchgl %%ebx, %0" "\n\t"
"ud2a ; .ascii \"xen\" ; cpuid" "\n\t"
"xchgl %%ebx, %0"
: "=&r" (regs.ebx), "=&c" (regs.ecx), "=&d" (regs.edx)
: "a" (regs.eax)
);
name[0] = regs.ebx;
name[1] = regs.ecx;
name[2] = regs.edx;
name[3] = 0;
if (0 == strcmp(CPUID_XEN_HYPERVISOR_VENDOR_STRING, (const char*)name)) {
return TRUE;
}
/* Passed checks. But native and anything non-Xen would #UD before here. */
NOT_TESTED();
Log("Xen detected but hypervisor unrecognized (Xen variant?)\n");
Log("CPUID 0x4000 0000: eax=%x ebx=%x ecx=%x edx=%x\n",
regs.eax, regs.ebx, regs.ecx, regs.edx);
#endif
return FALSE;
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_SLC64Supported --
*
* Access the backdoor with an SLC64 control query. This is used
* to determine if we are running in a VM that supports SLC64.
* This function should only be called after determining that the
* backdoor is present with Hostinfo_TouchBackdoor().
*
* Results:
* TRUE if the outer VM supports SLC64.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_SLC64Supported(void)
{
#if defined(__i386__) || defined(__x86_64__)
return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SLC64);
#else
return FALSE;
#endif
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_NestedHVReplaySupported --
*
* Access the backdoor with a HV replay control query. This is used
* to determine if we are running in a VM that supports nested HV replay.
* This function should only be called after determining that the
* backdoor is present with Hostinfo_TouchBackdoor().
*
* Results:
* TRUE if the outer VM supports nexted HV replay.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_NestedHVReplaySupported(void)
{
#if defined(__i386__) || defined(__x86_64__)
return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_HV_REPLAY_OK);
#else
return FALSE;
#endif
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_SynchronizedVTSCs --
*
* Access the backdoor to determine if the VCPUs' TSCs are
* synchronized.
*
* Results:
* TRUE if the outer VM provides synchronized VTSCs.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_SynchronizedVTSCs(void)
{
#if defined(__i386__) || defined(__x86_64__)
return Hostinfo_VCPUInfoBackdoor(BDOOR_CMD_VCPU_SYNC_VTSCS);
#else
return FALSE;
#endif
}
#if defined(_WIN32)
#if defined(_WIN64)
// from touchBackdoorMasm64.asm
void Hostinfo_BackdoorInOut(Backdoor_proto *myBp);
#endif
/*
*----------------------------------------------------------------------
*
* Hostinfo_TouchBackDoor --
*
* Access the backdoor. This is used to determine if we are
* running in a VM or on a physical host. On a physical host
* this should generate a GP which we catch and thereby determine
* that we are not in a VM. However some OSes do not handle the
* GP correctly and the process continues running returning garbage.
* In this case we check the EBX register which should be
* BDOOR_MAGIC if the IN was handled in a VM. Based on this we
* return either TRUE or FALSE.
*
* Results:
* TRUE if we succesfully accessed the backdoor, FALSE or segfault
* if not.
*
* Side effects:
* Exception if not in a VM.
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_TouchBackDoor(void)
{
uint32 ebxval;
#if defined(_WIN64)
Backdoor_proto bp;
bp.in.ax.quad = BDOOR_MAGIC;
bp.in.size = ~BDOOR_MAGIC;
bp.in.cx.quad = BDOOR_CMD_GETVERSION;
bp.in.dx.quad = BDOOR_PORT;
Hostinfo_BackdoorInOut(&bp);
ebxval = bp.out.bx.words.low;
#else // _WIN64
_asm {
push edx
push ecx
push ebx
mov ecx, BDOOR_CMD_GETVERSION
mov ebx, ~BDOOR_MAGIC
mov eax, BDOOR_MAGIC
mov dx, BDOOR_PORT
in eax, dx
mov ebxval, ebx
pop ebx
pop ecx
pop edx
}
#endif // _WIN64
return (ebxval == BDOOR_MAGIC) ? TRUE : FALSE;
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_TouchVirtualPC --
*
* Access MS Virtual PC's backdoor. This is used to determine if
* we are running in a MS Virtual PC or on a physical host. Works
* the same as Hostinfo_TouchBackDoor, except the entry to MS VPC
* is an invalid opcode instead or writing to a port. Since
* MS VPC is 32-bit only, the WIN64 path returns FALSE.
* See: See: http://www.codeproject.com/KB/system/VmDetect.aspx
*
* Results:
* TRUE if we succesfully accessed MS Virtual PC, FALSE or
* segfault if not.
*
* Side effects:
* Exception if not in a VM.
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_TouchVirtualPC(void)
{
#if defined(_WIN64)
return FALSE; // MS Virtual PC is 32-bit only
#else // _WIN32
uint32 ebxval;
_asm {
push ebx
mov ebx, 0
mov eax, 1 // Virtual PC function number
// execute invalid opcode to call into MS Virtual PC
__emit 0Fh
__emit 3Fh
__emit 07h
__emit 0Bh
mov ebxval, ebx
pop ebx
}
return !ebxval; // ebx is zero if inside Virtual PC
#endif
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_NestingSupported --
*
* Access the backdoor with a nesting control query. This is used
* to determine if we are running in a VM that supports nesting.
* This function should only be called after determining that the
* backdoor is present with Hostinfo_TouchBackdoor().
*
* Results:
* TRUE if the outer VM supports nesting.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_NestingSupported(void)
{
uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL;
uint32 result;
#if defined(_WIN64)
Backdoor_proto bp;
bp.in.ax.quad = BDOOR_MAGIC;
bp.in.cx.quad = cmd;
bp.in.dx.quad = BDOOR_PORT;
Hostinfo_BackdoorInOut(&bp);
result = bp.out.ax.words.low;
#else
_asm {
push edx
push ecx
mov ecx, cmd
mov eax, BDOOR_MAGIC
mov dx, BDOOR_PORT
in eax, dx
mov result, eax
pop ecx
pop edx
}
#endif
if (result >= NESTING_CONTROL_QUERY && result != ~0U) {
return TRUE;
}
return FALSE;
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_VCPUInfoBackdoor --
*
* Access the backdoor with an VCPU info query. This is used to
* determine whether a VCPU supports a particular feature,
* determined by 'bit'. This function should only be called after
* determining that the backdoor is present with
* Hostinfo_TouchBackdoor().
*
* Results:
* TRUE if the outer VM supports the feature.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_VCPUInfoBackdoor(unsigned bit)
{
uint32 cmd = BDOOR_CMD_GET_VCPU_INFO;
uint32 result;
#if defined(_WIN64)
Backdoor_proto bp;
bp.in.ax.quad = BDOOR_MAGIC;
bp.in.cx.quad = cmd;
bp.in.dx.quad = BDOOR_PORT;
Hostinfo_BackdoorInOut(&bp);
result = bp.out.ax.words.low;
#else
_asm {
push edx
push ecx
mov ecx, cmd
mov eax, BDOOR_MAGIC
mov dx, BDOOR_PORT
in eax, dx
mov result, eax
pop ecx
pop edx
}
#endif
/* If reserved bit is 1, this command wasn't implemented. */
return (result & (1 << BDOOR_CMD_VCPU_RESERVED)) == 0 &&
(result & (1 << bit)) != 0;
}
#else
/*
*----------------------------------------------------------------------
*
* Hostinfo_TouchBackDoor --
*
* Access the backdoor. This is used to determine if we are
* running in a VM or on a physical host. On a physical host
* this should generate a GP which we catch and thereby determine
* that we are not in a VM. However some OSes do not handle the
* GP correctly and the process continues running returning garbage.
* In this case we check the EBX register which should be
* BDOOR_MAGIC if the IN was handled in a VM. Based on this we
* return either TRUE or FALSE.
*
* Results:
* TRUE if we succesfully accessed the backdoor, FALSE or segfault
* if not.
*
* Side effects:
* Exception if not in a VM.
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_TouchBackDoor(void)
{
#if defined(__i386__) || defined(__x86_64__)
uint32 eax;
uint32 ebx;
uint32 ecx;
__asm__ __volatile__(
# if defined __PIC__ && !vm_x86_64 // %ebx is reserved by the compiler.
"xchgl %%ebx, %1" "\n\t"
"inl %%dx, %%eax" "\n\t"
"xchgl %%ebx, %1"
: "=a" (eax),
"=&rm" (ebx),
# else
"inl %%dx, %%eax"
: "=a" (eax),
"=b" (ebx),
# endif
"=c" (ecx)
: "0" (BDOOR_MAGIC),
"1" (~BDOOR_MAGIC),
"2" (BDOOR_CMD_GETVERSION),
"d" (BDOOR_PORT)
);
if (ebx == BDOOR_MAGIC) {
return TRUE;
}
#endif
return FALSE;
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_TouchVirtualPC --
*
* Access MS Virtual PC's backdoor. This is used to determine if
* we are running in a MS Virtual PC or on a physical host. Works
* the same as Hostinfo_TouchBackDoor, except the entry to MS VPC
* is an invalid opcode instead or writing to a port. Since
* MS VPC is 32-bit only, the 64-bit path returns FALSE.
* See: http://www.codeproject.com/KB/system/VmDetect.aspx
*
* Results:
* TRUE if we succesfully accessed MS Virtual PC, FALSE or
* segfault if not.
*
* Side effects:
* Exception if not in a VM.
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_TouchVirtualPC(void)
{
#if defined vm_x86_64
return FALSE;
#else
uint32 ebxval;
__asm__ __volatile__ (
# if defined __PIC__ // %ebx is reserved by the compiler.
"xchgl %%ebx, %1" "\n\t"
".long 0x0B073F0F" "\n\t"
"xchgl %%ebx, %1"
: "=&rm" (ebxval)
: "a" (1),
"0" (0)
# else
".long 0x0B073F0F"
: "=b" (ebxval)
: "a" (1),
"b" (0)
# endif
);
return !ebxval; // %%ebx is zero if inside Virtual PC
#endif
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_NestingSupported --
*
* Access the backdoor with a nesting control query. This is used
* to determine if we are running inside a VM that supports nesting.
* This function should only be called after determining that the
* backdoor is present with Hostinfo_TouchBackdoor().
*
* Results:
* TRUE if the outer VM supports nesting.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_NestingSupported(void)
{
#if defined(__i386__) || defined(__x86_64__)
uint32 cmd = NESTING_CONTROL_QUERY << 16 | BDOOR_CMD_NESTING_CONTROL;
uint32 result;
__asm__ __volatile__(
"inl %%dx, %%eax"
: "=a" (result)
: "0" (BDOOR_MAGIC),
"c" (cmd),
"d" (BDOOR_PORT)
);
if (result >= NESTING_CONTROL_QUERY && result != ~0U) {
return TRUE;
}
#endif
return FALSE;
}
/*
*----------------------------------------------------------------------
*
* Hostinfo_VCPUInfoBackdoor --
*
* Access the backdoor with an VCPU info query. This is used to
* determine whether a VCPU supports a particular feature,
* determined by 'bit'. This function should only be called after
* determining that the backdoor is present with
* Hostinfo_TouchBackdoor().
*
* Results:
* TRUE if the outer VM supports the feature.
* FALSE otherwise.
*
* Side effects:
* Exception if not in a VM, so don't do that!
*
*----------------------------------------------------------------------
*/
Bool
Hostinfo_VCPUInfoBackdoor(unsigned bit)
{
#if defined(__i386__) || defined(__x86_64__)
uint32 result;
__asm__ __volatile__(
"inl %%dx, %%eax"
: "=a" (result)
: "0" (BDOOR_MAGIC),
"c" (BDOOR_CMD_GET_VCPU_INFO),
"d" (BDOOR_PORT)
);
/* If reserved bit is 1, this command wasn't implemented. */
return (result & (1 << BDOOR_CMD_VCPU_RESERVED)) == 0 &&
(result & (1 << bit)) != 0;
#endif
return FALSE;
}
#endif

View File

@@ -0,0 +1,605 @@
/*********************************************************
* Copyright (C) 1999-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* message.c --
*
* Second layer of the internal communication channel between guest
* applications and vmware
*
* Build a generic messaging system between guest applications and vmware.
*
* The protocol is not completely symmetrical, because:
* . basic requests can only be sent by guest applications (when vmware
* wants to post a message to a guest application, the message will be
* really fetched only when the guest application will poll for new
* available messages)
* . several guest applications can talk to vmware, while the contrary is
* not true
*
* Operations that are not atomic (in terms of number of backdoor calls)
* can be aborted by vmware if a checkpoint/restore occurs in the middle of
* such an operation. This layer takes care of retrying those operations.
*/
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__KERNEL__) || defined(_KERNEL) || defined(KERNEL)
# include "kernelStubs.h"
#else
# include <stdio.h>
# include <stdlib.h>
# include "debug.h"
#endif
#include "backdoor_def.h"
#include "guest_msg_def.h"
#include "backdoor.h"
#include "message.h"
#if defined(MESSAGE_DEBUG)
# define MESSAGE_LOG(...) Warning(__VA_ARGS__)
#else
# define MESSAGE_LOG(...)
#endif
/* The channel object */
struct Message_Channel {
/* Identifier */
uint16 id;
/* Reception buffer */
/* Data */
unsigned char *in;
/* Allocated size */
size_t inAlloc;
/* The cookie */
uint32 cookieHigh;
uint32 cookieLow;
};
/*
*-----------------------------------------------------------------------------
*
* Message_Open --
*
* Open a communication channel
*
* Result:
* An allocated Message_Channel on success
* NULL on failure
*
* Side-effects:
* None
*
*-----------------------------------------------------------------------------
*/
Message_Channel *
Message_Open(uint32 proto) // IN
{
Message_Channel *chan;
uint32 flags;
Backdoor_proto bp;
chan = (Message_Channel *)malloc(sizeof(*chan));
if (chan == NULL) {
goto error_quit;
}
flags = GUESTMSG_FLAG_COOKIE;
retry:
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_OPEN;
/* IN: Magic number of the protocol and flags */
bp.in.size = proto | flags;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
if (flags) {
/* Cookies not supported. Fall back to no cookie. --hpreg */
flags = 0;
goto retry;
}
MESSAGE_LOG("Message: Unable to open a communication channel\n");
goto error_quit;
}
/* OUT: Id and cookie */
chan->id = bp.in.dx.halfs.high;
chan->cookieHigh = bp.out.si.word;
chan->cookieLow = bp.out.di.word;
/* Initialize the channel */
chan->in = NULL;
chan->inAlloc = 0;
return chan;
error_quit:
free(chan);
chan = NULL;
return NULL;
}
/*
*-----------------------------------------------------------------------------
*
* Message_Send --
*
* Send a message over a communication channel
*
* Result:
* TRUE on success
* FALSE on failure (the message is discarded by vmware)
*
* Side-effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
Message_Send(Message_Channel *chan, // IN/OUT
const unsigned char *buf, // IN
size_t bufSize) // IN
{
const unsigned char *myBuf;
size_t myBufSize;
Backdoor_proto bp;
retry:
myBuf = buf;
myBufSize = bufSize;
/*
* Send the size.
*/
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_SENDSIZE;
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
/* IN: Size */
bp.in.size = myBufSize;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
MESSAGE_LOG("Message: Unable to send a message over the communication "
"channel %u\n", chan->id);
return FALSE;
}
if (bp.in.cx.halfs.high & MESSAGE_STATUS_HB) {
/*
* High-bandwidth backdoor port supported. Send the message in one
* backdoor operation. --hpreg
*/
if (myBufSize) {
Backdoor_proto_hb bphb;
bphb.in.bx.halfs.low = BDOORHB_CMD_MESSAGE;
bphb.in.bx.halfs.high = MESSAGE_STATUS_SUCCESS;
bphb.in.dx.halfs.high = chan->id;
bphb.in.bp.word = chan->cookieHigh;
bphb.in.dstAddr = chan->cookieLow;
bphb.in.size = myBufSize;
bphb.in.srcAddr = (uintptr_t) myBuf;
Backdoor_HbOut(&bphb);
if ((bphb.in.bx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
if ((bphb.in.bx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
/* A checkpoint occurred. Retry the operation. --hpreg */
goto retry;
}
MESSAGE_LOG("Message: Unable to send a message over the "
"communication channel %u\n", chan->id);
return FALSE;
}
}
} else {
/*
* High-bandwidth backdoor port not supported. Send the message, 4 bytes
* at a time. --hpreg
*/
for (;;) {
if (myBufSize == 0) {
/* We are done */
break;
}
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_SENDPAYLOAD;
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
/* IN: Piece of message */
/*
* Beware in case we are not allowed to read extra bytes beyond the
* end of the buffer.
*/
switch (myBufSize) {
case 1:
bp.in.size = myBuf[0];
myBufSize -= 1;
break;
case 2:
bp.in.size = myBuf[0] | myBuf[1] << 8;
myBufSize -= 2;
break;
case 3:
bp.in.size = myBuf[0] | myBuf[1] << 8 | myBuf[2] << 16;
myBufSize -= 3;
break;
default:
bp.in.size = *(const uint32 *)myBuf;
myBufSize -= 4;
break;
}
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
/* A checkpoint occurred. Retry the operation. --hpreg */
goto retry;
}
MESSAGE_LOG("Message: Unable to send a message over the "
"communication channel %u\n", chan->id);
return FALSE;
}
myBuf += 4;
}
}
return TRUE;
}
/*
*-----------------------------------------------------------------------------
*
* Message_Receive --
*
* If vmware has posted a message for this channel, retrieve it
*
* Result:
* TRUE on success (bufSize is 0 if there is no message)
* FALSE on failure
*
* Side-effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
Message_Receive(Message_Channel *chan, // IN/OUT
unsigned char **buf, // OUT
size_t *bufSize) // OUT
{
Backdoor_proto bp;
size_t myBufSize;
unsigned char *myBuf;
retry:
/*
* Is there a message waiting for our retrieval?
*/
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVSIZE;
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
MESSAGE_LOG("Message: Unable to poll for messages over the "
"communication channel %u\n", chan->id);
return FALSE;
}
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_DORECV) == 0) {
/* No message to retrieve */
*bufSize = 0;
return TRUE;
}
/*
* Receive the size.
*/
/* OUT: Type */
if (bp.in.dx.halfs.high != MESSAGE_TYPE_SENDSIZE) {
MESSAGE_LOG("Message: Protocol error. Expected a "
"MESSAGE_TYPE_SENDSIZE request from vmware\n");
return FALSE;
}
/* OUT: Size */
myBufSize = bp.out.bx.word;
/*
* Allocate an extra byte for a trailing NUL character. The code that will
* deal with this message may not know about binary strings, and may expect
* a C string instead. --hpreg
*/
if (myBufSize + 1 > chan->inAlloc) {
myBuf = (unsigned char *)realloc(chan->in, myBufSize + 1);
if (myBuf == NULL) {
MESSAGE_LOG("Message: Not enough memory to receive a message over "
"the communication channel %u\n", chan->id);
goto error_quit;
}
chan->in = myBuf;
chan->inAlloc = myBufSize + 1;
}
*bufSize = myBufSize;
myBuf = *buf = chan->in;
if (bp.in.cx.halfs.high & MESSAGE_STATUS_HB) {
/*
* High-bandwidth backdoor port supported. Receive the message in one
* backdoor operation. --hpreg
*/
if (myBufSize) {
Backdoor_proto_hb bphb;
bphb.in.bx.halfs.low = BDOORHB_CMD_MESSAGE;
bphb.in.bx.halfs.high = MESSAGE_STATUS_SUCCESS;
bphb.in.dx.halfs.high = chan->id;
bphb.in.srcAddr = chan->cookieHigh;
bphb.in.bp.word = chan->cookieLow;
bphb.in.size = myBufSize;
bphb.in.dstAddr = (uintptr_t) myBuf;
Backdoor_HbIn(&bphb);
if ((bphb.in.bx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
if ((bphb.in.bx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
/* A checkpoint occurred. Retry the operation. --hpreg */
goto retry;
}
MESSAGE_LOG("Message: Unable to receive a message over the "
"communication channel %u\n", chan->id);
goto error_quit;
}
}
} else {
/*
* High-bandwidth backdoor port not supported. Receive the message, 4
* bytes at a time. --hpreg
*/
for (;;) {
if (myBufSize == 0) {
/* We are done */
break;
}
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVPAYLOAD;
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
/* IN: Status for the previous request (that succeeded) */
bp.in.size = MESSAGE_STATUS_SUCCESS;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
/* A checkpoint occurred. Retry the operation. --hpreg */
goto retry;
}
MESSAGE_LOG("Message: Unable to receive a message over the "
"communication channel %u\n", chan->id);
goto error_quit;
}
/* OUT: Type */
if (bp.in.dx.halfs.high != MESSAGE_TYPE_SENDPAYLOAD) {
MESSAGE_LOG("Message: Protocol error. Expected a "
"MESSAGE_TYPE_SENDPAYLOAD from vmware\n");
goto error_quit;
}
/* OUT: Piece of message */
/*
* Beware in case we are not allowed to write extra bytes beyond the
* end of the buffer. --hpreg
*/
switch (myBufSize) {
case 1:
myBuf[0] = bp.out.bx.word & 0xff;
myBufSize -= 1;
break;
case 2:
myBuf[0] = bp.out.bx.word & 0xff;
myBuf[1] = (bp.out.bx.word >> 8) & 0xff;
myBufSize -= 2;
break;
case 3:
myBuf[0] = bp.out.bx.word & 0xff;
myBuf[1] = (bp.out.bx.word >> 8) & 0xff;
myBuf[2] = (bp.out.bx.word >> 16) & 0xff;
myBufSize -= 3;
break;
default:
*(uint32 *)myBuf = bp.out.bx.word;
myBufSize -= 4;
break;
}
myBuf += 4;
}
}
/* Write a trailing NUL just after the message. --hpreg */
chan->in[*bufSize] = '\0';
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVSTATUS;
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
/* IN: Status for the previous request (that succeeded) */
bp.in.size = MESSAGE_STATUS_SUCCESS;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_CPT) != 0) {
/* A checkpoint occurred. Retry the operation. --hpreg */
goto retry;
}
MESSAGE_LOG("Message: Unable to receive a message over the "
"communication channel %u\n", chan->id);
goto error_quit;
}
return TRUE;
error_quit:
/* IN: Type */
if (myBufSize == 0) {
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVSTATUS;
} else {
bp.in.cx.halfs.high = MESSAGE_TYPE_RECVPAYLOAD;
}
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
/* IN: Status for the previous request (that failed) */
bp.in.size = 0;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
MESSAGE_LOG("Message: Unable to signal an error of reception over the "
"communication channel %u\n", chan->id);
return FALSE;
}
return FALSE;
}
/*
*-----------------------------------------------------------------------------
*
* Message_Close --
*
* Close a communication channel
*
* Result:
* TRUE on success, the channel is destroyed
* FALSE on failure
*
* Side-effects:
* None
*
*-----------------------------------------------------------------------------
*/
Bool
Message_Close(Message_Channel *chan) // IN/OUT
{
Backdoor_proto bp;
Bool ret = TRUE;
/* IN: Type */
bp.in.cx.halfs.high = MESSAGE_TYPE_CLOSE;
/* IN: Id and cookie */
bp.in.dx.halfs.high = chan->id;
bp.in.si.word = chan->cookieHigh;
bp.in.di.word = chan->cookieLow;
bp.in.cx.halfs.low = BDOOR_CMD_MESSAGE;
Backdoor(&bp);
/* OUT: Status */
if ((bp.in.cx.halfs.high & MESSAGE_STATUS_SUCCESS) == 0) {
MESSAGE_LOG("Message: Unable to close the communication channel %u\n",
chan->id);
ret = FALSE;
}
free(chan->in);
chan->in = NULL;
free(chan);
return ret;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,416 @@
/*********************************************************
* Copyright (C) 2009-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* utilMem.c --
*
* misc util functions
*/
#ifdef _WIN32
#include <windows.h>
#endif
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include "vm_assert.h"
#include "util.h"
#ifdef __APPLE__
#include <TargetConditionals.h>
#if !defined TARGET_OS_IPHONE
#define TARGET_OS_IPHONE 0
#endif
#endif
static NORETURN void UtilAllocationFailure0(void);
static NORETURN void UtilAllocationFailure1(int bugNumber,
const char *file, int lineno);
static void
UtilAllocationFailure0(void)
{
Panic("Unrecoverable memory allocation failure\n");
}
static void
UtilAllocationFailure1(int bugNumber, const char *file, int lineno)
{
if (bugNumber == -1) {
Panic("Unrecoverable memory allocation failure at %s:%d\n",
file, lineno);
} else {
Panic("Unrecoverable memory allocation failure at %s:%d. Bug "
"number: %d\n", file, lineno, bugNumber);
}
}
/*
*-----------------------------------------------------------------------------
*
* UtilSafeMalloc0 --
* UtilSafeMalloc1 --
* Helper function for malloc
*
* Results:
* Pointer to the dynamically allocated memory.
*
* Side effects:
* May Panic if ran out of memory.
*
*-----------------------------------------------------------------------------
*/
void *
UtilSafeMalloc0(size_t size) // IN:
{
void *result = malloc(size);
if (result == NULL && size != 0) {
UtilAllocationFailure0();
}
return result;
}
void *
UtilSafeMalloc1(size_t size, // IN:
int bugNumber, // IN:
const char *file, // IN:
int lineno) // IN:
{
void *result = malloc(size);
if (result == NULL && size != 0) {
UtilAllocationFailure1(bugNumber, file, lineno);
}
return result;
}
/*
*-----------------------------------------------------------------------------
*
* UtilSafeRealloc0 --
* UtilSafeRealloc1 --
* Helper function for realloc
*
* Results:
* Pointer to the dynamically allocated memory.
*
* Side effects:
* May Panic if ran out of memory.
*
*-----------------------------------------------------------------------------
*/
void *
UtilSafeRealloc0(void *ptr, // IN:
size_t size) // IN:
{
void *result = realloc(ptr, size);
if (result == NULL && size != 0) {
UtilAllocationFailure0();
}
return result;
}
void *
UtilSafeRealloc1(void *ptr, // IN:
size_t size, // IN:
int bugNumber, // IN:
const char *file, // IN:
int lineno) // IN:
{
void *result = realloc(ptr, size);
if (result == NULL && size != 0) {
UtilAllocationFailure1(bugNumber, file, lineno);
}
return result;
}
/*
*-----------------------------------------------------------------------------
*
* UtilSafeCalloc0 --
* UtilSafeCalloc1 --
* Helper function for calloc
*
* Results:
* Pointer to the dynamically allocated memory.
*
* Side effects:
* May Panic if ran out of memory.
*
*-----------------------------------------------------------------------------
*/
void *
UtilSafeCalloc0(size_t nmemb, // IN:
size_t size) // IN:
{
void *result = calloc(nmemb, size);
if (result == NULL && nmemb != 0 && size != 0) {
UtilAllocationFailure0();
}
return result;
}
void *
UtilSafeCalloc1(size_t nmemb, // IN:
size_t size, // IN:
int bugNumber, // IN:
const char *file, // IN:
int lineno) // IN:
{
void *result = calloc(nmemb, size);
if (result == NULL && nmemb != 0 && size != 0) {
UtilAllocationFailure1(bugNumber, file, lineno);
}
return result;
}
/*
*-----------------------------------------------------------------------------
*
* Util_SafeStrdup --
* Helper function for strdup
*
* Results:
* Pointer to the dynamically allocated, duplicate string
*
* Side effects:
* May Panic if ran out of memory.
*
*-----------------------------------------------------------------------------
*/
char *
UtilSafeStrdup0(const char *s) // IN:
{
char *result;
if (s == NULL) {
return NULL;
}
#if defined(_WIN32)
if ((result = _strdup(s)) == NULL) {
#else
if ((result = strdup(s)) == NULL) {
#endif
UtilAllocationFailure0();
}
return result;
}
char *
UtilSafeStrdup1(const char *s, // IN:
int bugNumber, // IN:
const char *file, // IN:
int lineno) // IN:
{
char *result;
if (s == NULL) {
return NULL;
}
#if defined(_WIN32)
if ((result = _strdup(s)) == NULL) {
#else
if ((result = strdup(s)) == NULL) {
#endif
UtilAllocationFailure1(bugNumber, file, lineno);
}
return result;
}
/*
*-----------------------------------------------------------------------------
*
* Util_SafeStrndup --
*
* Returns a string consisting of first n characters of 's' if 's' has
* length >= 'n', otherwise returns a string duplicate of 's'.
*
* Results:
* Pointer to the duplicated string.
*
* Side effects:
* May Panic if ran out of memory.
*
*-----------------------------------------------------------------------------
*/
char *
UtilSafeStrndup0(const char *s, // IN:
size_t n) // IN:
{
size_t size;
char *copy;
const char *null;
size_t newSize;
if (s == NULL) {
return NULL;
}
null = memchr(s, '\0', n);
size = null ? (size_t)(null - s) : n;
newSize = size + 1;
if (newSize < size) { // Prevent integer overflow
copy = NULL;
} else {
copy = malloc(newSize);
}
if (copy == NULL) {
UtilAllocationFailure0();
}
copy[size] = '\0';
return (char *) memcpy(copy, s, size);
}
char *
UtilSafeStrndup1(const char *s, // IN:
size_t n, // IN:
int bugNumber, // IN:
const char *file, // IN:
int lineno) // IN:
{
size_t size;
char *copy;
const char *null;
size_t newSize;
if (s == NULL) {
return NULL;
}
null = memchr(s, '\0', n);
size = null ? (size_t)(null - s) : n;
newSize = size + 1;
if (newSize < size) { // Prevent integer overflow
copy = NULL;
} else {
copy = malloc(newSize);
}
if (copy == NULL) {
UtilAllocationFailure1(bugNumber, file, lineno);
}
copy[size] = '\0';
return (char *) memcpy(copy, s, size);
}
void *
Util_Memcpy(void *dest,
const void *src,
size_t count)
{
#if defined(__x86_64__) || defined(__i386__)
uintptr_t align = ((uintptr_t)dest | (uintptr_t)src | count);
#if defined __GNUC__
#if defined(__x86_64__)
size_t dummy0;
void *dummy1;
void *dummy2;
if ((align & 7) == 0) {
__asm__ __volatile__("\t"
"cld" "\n\t"
"rep ; movsq" "\n"
: "=c" (dummy0), "=D" (dummy1), "=S" (dummy2)
: "0" (count >> 3), "1" (dest), "2" (src)
: "memory", "cc"
);
return dest;
} else if ((align & 3) == 0) {
__asm__ __volatile__("\t"
"cld" "\n\t"
"rep ; movsd" "\n"
: "=c" (dummy0), "=D" (dummy1), "=S" (dummy2)
: "0" (count >> 2), "1" (dest), "2" (src)
: "memory", "cc"
);
return dest;
}
#elif defined(__i386__)
size_t dummy0;
void *dummy1;
void *dummy2;
if ((align & 3) == 0) {
__asm__ __volatile__("\t"
"cld" "\n\t"
"rep ; movsd" "\n"
: "=c" (dummy0), "=D" (dummy1), "=S" (dummy2)
: "0" (count >> 2), "1" (dest), "2" (src)
: "memory", "cc"
);
return dest;
}
#endif
#elif defined _MSC_VER
#if defined(__x86_64__)
if ((align & 7) == 0) {
__movsq((uint64 *)dest, (uint64 *)src, count >> 3);
return dest;
} else if ((align & 3) == 0) {
__movsd((unsigned long *)dest, (unsigned long *)src, count >> 2);
return dest;
}
#elif defined(__i386__)
if ((((uintptr_t)dest | (uintptr_t)src | count) & 3) == 0) {
__movsd((unsigned long *)dest, (unsigned long *)src, count >> 2);
return dest;
}
#endif
#endif
#endif
memcpy(dest, src, count);
return dest;
}

View File

@@ -0,0 +1,300 @@
/*********************************************************
* Copyright (C) 2006-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* vmcheck.c --
*
* Utility functions for discovering our virtualization status.
*/
#include <stdlib.h>
#include <string.h>
#ifdef WINNT_DDK
# include <ntddk.h>
#endif
#include "vmware.h"
/*
* #include "vm_version.h"
* #include "vm_tools_version.h"
*/
#define VMX_TYPE_UNSET 0
#define VERSION_MAGIC 0x6
#if !defined(WINNT_DDK)
# include "hostinfo.h"
/* # include "str.h" */
# define Str_Strcmp(s1, s2) strcmp(s1, s2)
#endif
/*
* backdoor.h includes some files which redefine constants in ntddk.h. Ignore
* warnings about these redefinitions for WIN32 platform.
*/
#ifdef WINNT_DDK
#pragma warning (push)
// Warning: Conditional expression is constant.
#pragma warning( disable:4127 )
#endif
#include "backdoor.h"
#ifdef WINNT_DDK
#pragma warning (pop)
#endif
#include "backdoor_def.h"
#include "debug.h"
typedef Bool (*SafeCheckFn)(void);
#if !defined(_WIN32)
# include "vmsignal.h"
# include "setjmp.h"
static sigjmp_buf jmpBuf;
static Bool jmpIsSet;
/*
*----------------------------------------------------------------------
*
* VmCheckSegvHandler --
*
* Signal handler for segv. Return to the program state saved
* by a previous call to sigsetjmp, or Panic if sigsetjmp hasn't
* been called yet. This function never returns;
*
* Return Value:
* None.
*
* Side effects:
* See the manpage for sigsetjmp for details.
*
*----------------------------------------------------------------------
*/
static void
VmCheckSegvHandler(int clientData) // UNUSED
{
if (jmpIsSet) {
siglongjmp(jmpBuf, 1);
} else {
Panic("Received SEGV, exiting.");
}
}
#endif
/*
*----------------------------------------------------------------------
*
* VmCheckSafe --
*
* Calls a potentially unsafe function, trapping possible exceptions.
*
* Results:
*
* Return value of the passed function, or FALSE in case of exception.
*
* Side effects:
*
* Temporarily suppresses signals / SEH exceptions
*
*----------------------------------------------------------------------
*/
static Bool
VmCheckSafe(SafeCheckFn checkFn)
{
Bool result = FALSE;
/*
* On a real host this call should cause a GP and we catch
* that and set result to FALSE.
*/
#if defined(_WIN32)
__try {
result = checkFn();
} __except(EXCEPTION_EXECUTE_HANDLER) {
/* no op */
}
#else
do {
int signals[] = {
SIGILL,
SIGSEGV,
};
struct sigaction olds[ARRAYSIZE(signals)];
if (Signal_SetGroupHandler(signals, olds, ARRAYSIZE(signals),
VmCheckSegvHandler) == 0) {
Warning("%s: Failed to set signal handlers.\n", __FUNCTION__);
break;
}
if (sigsetjmp(jmpBuf, TRUE) == 0) {
jmpIsSet = TRUE;
result = checkFn();
} else {
jmpIsSet = FALSE;
}
if (Signal_ResetGroupHandler(signals, olds, ARRAYSIZE(signals)) == 0) {
Warning("%s: Failed to reset signal handlers.\n", __FUNCTION__);
}
} while (0);
#endif
return result;
}
/*
*----------------------------------------------------------------------
*
* VmCheck_GetVersion --
*
* Retrieve the version of VMware that's running on the
* other side of the backdoor.
*
* Return value:
* TRUE on success
* *version contains the VMX version
* *type contains the VMX type
* FALSE on failure
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
Bool
VmCheck_GetVersion(uint32 *version, // OUT
uint32 *type) // OUT
{
Backdoor_proto bp;
ASSERT(version);
ASSERT(type);
/* Make sure EBX does not contain BDOOR_MAGIC */
bp.in.size = ~BDOOR_MAGIC;
/* Make sure ECX does not contain any known VMX type */
bp.in.cx.halfs.high = 0xFFFF;
bp.in.cx.halfs.low = BDOOR_CMD_GETVERSION;
Backdoor(&bp);
if (bp.out.ax.word == 0xFFFFFFFF) {
/*
* No backdoor device there. This code is not executing in a VMware
* virtual machine. --hpreg
*/
return FALSE;
}
if (bp.out.bx.word != BDOOR_MAGIC) {
return FALSE;
}
*version = bp.out.ax.word;
/*
* Old VMXs (workstation and express) didn't set their type. In that case,
* our special pattern will still be there. --hpreg
*/
/*
* Need to expand this out since the toolchain's gcc doesn't like mixing
* integral types and enums in the same trinary operator.
*/
if (bp.in.cx.halfs.high == 0xFFFF)
*type = VMX_TYPE_UNSET;
else
*type = bp.out.cx.word;
return TRUE;
}
/*
*----------------------------------------------------------------------
*
* VmCheck_IsVirtualWorld --
*
* Verify that we're running in a VM & we're version compatible with our
* environment.
*
* Return value:
* TRUE if we're in a virtual machine, FALSE otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Bool
VmCheck_IsVirtualWorld(void)
{
uint32 version;
uint32 dummy;
#if !defined(WINNT_DDK)
if (VmCheckSafe(Hostinfo_TouchXen)) {
Debug("%s: detected Xen.\n", __FUNCTION__);
return FALSE;
}
if (VmCheckSafe(Hostinfo_TouchVirtualPC)) {
Debug("%s: detected Virtual PC.\n", __FUNCTION__);
return FALSE;
}
if (!VmCheckSafe(Hostinfo_TouchBackDoor)) {
Debug("%s: backdoor not detected.\n", __FUNCTION__);
return FALSE;
}
/* It should be safe to use the backdoor without a crash handler now. */
VmCheck_GetVersion(&version, &dummy);
#else
/*
* The Win32 vmwvaudio driver uses this function, so keep the old,
* VMware-only check.
*/
__try {
VmCheck_GetVersion(&version, &dummy);
} __except (GetExceptionCode() == STATUS_PRIVILEGED_INSTRUCTION) {
return FALSE;
}
#endif
if (version != VERSION_MAGIC) {
Debug("The version of this program is incompatible with your platform.\n");
return FALSE;
}
return TRUE;
}

View File

@@ -0,0 +1,123 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* vmsignal.c --
*
* Posix signal handling utility functions
*
*/
#ifndef VMX86_DEVEL
#endif
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "vmsignal.h"
/*
* Signal_SetGroupHandler --
*
* Set a signal handler for a group of signals.
* We carefully ensure that if the handler is only used to handle the
* signals of the group, the handling of all the signals of the group is
* serialized, which means that the handler is not re-entrant.
*
* Return value:
* 1 on success
* 0 on failure (detail is displayed)
*
* Side effects:
* None
*
*/
int
Signal_SetGroupHandler(int const *signals, // IN
struct sigaction *olds, // OUT
unsigned int nr, // IN
void (*handler)(int signal)) // IN
{
unsigned int i;
struct sigaction new;
new.sa_handler = handler;
if (sigemptyset(&new.sa_mask)) {
fprintf(stderr, "Unable to empty a signal set: %s.\n\n", strerror(errno));
return 0;
}
for (i = 0; i < nr; i++) {
if (sigaddset(&new.sa_mask, signals[i])) {
fprintf(stderr, "Unable to add a signal to a signal set: %s.\n\n", strerror(errno));
return 0;
}
}
new.sa_flags = 0;
for (i = 0; i < nr; i++) {
if (sigaction(signals[i], &new, &olds[i])) {
fprintf(stderr, "Unable to modify the handler of the signal %d: %s.\n\n", signals[i], strerror(errno));
return 0;
}
}
return 1;
}
/*
* Signal_ResetGroupHandler --
*
* Reset the handler of each signal of a group of signals
*
* Return value:
* 1 on success
* 0 on failure (detail is displayed)
*
* Side effects:
* None
*
*/
int
Signal_ResetGroupHandler(int const *signals, // IN
struct sigaction const *olds, // IN
unsigned int nr) // IN
{
unsigned int i;
for (i = 0; i < nr; i++) {
if (sigaction(signals[i], &olds[i], NULL)) {
fprintf(stderr, "Unable to reset the handler of the signal %d: %s.\n\n", signals[i], strerror(errno));
return 0;
}
}
return 1;
}

View File

@@ -0,0 +1,22 @@
package main
import (
"fmt"
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/rpcvmx"
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/vmcheck"
)
func main() {
if !vmcheck.IsVirtualWorld() {
fmt.Println("not in a virtual world... :(")
return
}
version, typ := vmcheck.GetVersion()
fmt.Println(version, typ)
config := rpcvmx.NewConfig()
fmt.Println(config.GetString("foo", "foo"))
fmt.Println(config.GetString("bar", "foo"))
}

View File

@@ -0,0 +1,60 @@
/*********************************************************
* Copyright (C) 1999-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* backdoor.h --
*
* First layer of the internal communication channel between guest
* applications and vmware
*/
#ifndef _BACKDOOR_H_
#define _BACKDOOR_H_
#include "vm_basic_types.h"
#include "vm_assert.h"
#include "backdoor_types.h"
void
Backdoor(Backdoor_proto *bp); // IN/OUT
void
Backdoor_InOut(Backdoor_proto *bp); // IN/OUT
void
Backdoor_HbOut(Backdoor_proto_hb *bp); // IN/OUT
void
Backdoor_HbIn(Backdoor_proto_hb *bp); // IN/OUT
#endif /* _BACKDOOR_H_ */

View File

@@ -0,0 +1,40 @@
/*********************************************************
* Copyright (C) 2005-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* backdoorInt.h --
*
* Internal function prototypes for the real backdoor work.
*/
void BackdoorHbIn(Backdoor_proto_hb *bp);
void BackdoorHbOut(Backdoor_proto_hb *bp);

View File

@@ -0,0 +1,261 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* backdoor_def.h --
*
* This contains backdoor defines that can be included from
* an assembly language file.
*/
#ifndef _BACKDOOR_DEF_H_
#define _BACKDOOR_DEF_H_
/*
* If you want to add a new low-level backdoor call for a guest userland
* application, please consider using the GuestRpc mechanism instead. --hpreg
*/
#define BDOOR_MAGIC 0x564D5868
/* Low-bandwidth backdoor port. --hpreg */
#define BDOOR_PORT 0x5658
#define BDOOR_CMD_GETMHZ 1
/*
* BDOOR_CMD_APMFUNCTION is used by:
*
* o The FrobOS code, which instead should either program the virtual chipset
* (like the new BIOS code does, matthias offered to implement that), or not
* use any VM-specific code (which requires that we correctly implement
* "power off on CLI HLT" for SMP VMs, boris offered to implement that)
*
* o The old BIOS code, which will soon be jettisoned
*
* --hpreg
*/
#define BDOOR_CMD_APMFUNCTION 2 /* CPL0 only. */
#define BDOOR_CMD_GETDISKGEO 3
#define BDOOR_CMD_GETPTRLOCATION 4
#define BDOOR_CMD_SETPTRLOCATION 5
#define BDOOR_CMD_GETSELLENGTH 6
#define BDOOR_CMD_GETNEXTPIECE 7
#define BDOOR_CMD_SETSELLENGTH 8
#define BDOOR_CMD_SETNEXTPIECE 9
#define BDOOR_CMD_GETVERSION 10
#define BDOOR_CMD_GETDEVICELISTELEMENT 11
#define BDOOR_CMD_TOGGLEDEVICE 12
#define BDOOR_CMD_GETGUIOPTIONS 13
#define BDOOR_CMD_SETGUIOPTIONS 14
#define BDOOR_CMD_GETSCREENSIZE 15
#define BDOOR_CMD_MONITOR_CONTROL 16 /* Disabled by default. */
#define BDOOR_CMD_GETHWVERSION 17
#define BDOOR_CMD_OSNOTFOUND 18 /* CPL0 only. */
#define BDOOR_CMD_GETUUID 19
#define BDOOR_CMD_GETMEMSIZE 20
#define BDOOR_CMD_HOSTCOPY 21 /* Devel only. */
//#define BDOOR_CMD_SERVICE_VM 22 /* Not in use. Never shipped. */
#define BDOOR_CMD_GETTIME 23 /* Deprecated -> GETTIMEFULL. */
#define BDOOR_CMD_STOPCATCHUP 24
#define BDOOR_CMD_PUTCHR 25 /* Disabled by default. */
#define BDOOR_CMD_ENABLE_MSG 26 /* Devel only. */
#define BDOOR_CMD_GOTO_TCL 27 /* Devel only. */
#define BDOOR_CMD_INITPCIOPROM 28 /* CPL 0 only. */
//#define BDOOR_CMD_INT13 29 /* Not in use. */
#define BDOOR_CMD_MESSAGE 30
#define BDOOR_CMD_SIDT 31
#define BDOOR_CMD_SGDT 32
#define BDOOR_CMD_SLDT_STR 33
#define BDOOR_CMD_ISACPIDISABLED 34
//#define BDOOR_CMD_TOE 35 /* Not in use. */
#define BDOOR_CMD_ISMOUSEABSOLUTE 36
#define BDOOR_CMD_PATCH_SMBIOS_STRUCTS 37 /* CPL 0 only. */
#define BDOOR_CMD_MAPMEM 38 /* Devel only */
#define BDOOR_CMD_ABSPOINTER_DATA 39
#define BDOOR_CMD_ABSPOINTER_STATUS 40
#define BDOOR_CMD_ABSPOINTER_COMMAND 41
//#define BDOOR_CMD_TIMER_SPONGE 42 /* Not in use. */
#define BDOOR_CMD_PATCH_ACPI_TABLES 43 /* CPL 0 only. */
//#define BDOOR_CMD_DEVEL_FAKEHARDWARE 44 /* Not in use. */
#define BDOOR_CMD_GETHZ 45
#define BDOOR_CMD_GETTIMEFULL 46
#define BDOOR_CMD_STATELOGGER 47 /* Disabled by default. */
#define BDOOR_CMD_CHECKFORCEBIOSSETUP 48 /* CPL 0 only. */
#define BDOOR_CMD_LAZYTIMEREMULATION 49 /* CPL 0 only. */
#define BDOOR_CMD_BIOSBBS 50 /* CPL 0 only. */
//#define BDOOR_CMD_VASSERT 51 /* Not in use. */
#define BDOOR_CMD_ISGOSDARWIN 52
#define BDOOR_CMD_DEBUGEVENT 53
#define BDOOR_CMD_OSNOTMACOSXSERVER 54 /* CPL 0 only. */
#define BDOOR_CMD_GETTIMEFULL_WITH_LAG 55
#define BDOOR_CMD_ACPI_HOTPLUG_DEVICE 56 /* Devel only. */
#define BDOOR_CMD_ACPI_HOTPLUG_MEMORY 57 /* Devel only. */
#define BDOOR_CMD_ACPI_HOTPLUG_CBRET 58 /* Devel only. */
//#define BDOOR_CMD_GET_HOST_VIDEO_MODES 59 /* Not in use. */
#define BDOOR_CMD_ACPI_HOTPLUG_CPU 60 /* Devel only. */
//#define BDOOR_CMD_USB_HOTPLUG_MOUSE 61 /* Not in use. Never shipped. */
#define BDOOR_CMD_XPMODE 62 /* CPL 0 only. */
#define BDOOR_CMD_NESTING_CONTROL 63
#define BDOOR_CMD_FIRMWARE_INIT 64 /* CPL 0 only. */
#define BDOOR_CMD_FIRMWARE_ACPI_SERVICES 65 /* CPL 0 only. */
# define BDOOR_CMD_FAS_GET_TABLE_SIZE 0
# define BDOOR_CMD_FAS_GET_TABLE_DATA 1
# define BDOOR_CMD_FAS_GET_PLATFORM_NAME 2
# define BDOOR_CMD_FAS_GET_PCIE_OSC_MASK 3
# define BDOOR_CMD_FAS_GET_APIC_ROUTING 4
# define BDOOR_CMD_FAS_GET_TABLE_SKIP 5
# define BDOOR_CMD_FAS_GET_SLEEP_ENABLES 6
# define BDOOR_CMD_FAS_GET_HARD_RESET_ENABLE 7
#define BDOOR_CMD_SENDPSHAREHINTS 66
#define BDOOR_CMD_ENABLE_USB_MOUSE 67
#define BDOOR_CMD_GET_VCPU_INFO 68
# define BDOOR_CMD_VCPU_SLC64 0
# define BDOOR_CMD_VCPU_SYNC_VTSCS 1
# define BDOOR_CMD_VCPU_HV_REPLAY_OK 2
# define BDOOR_CMD_VCPU_LEGACY_X2APIC_OK 3
# define BDOOR_CMD_VCPU_RESERVED 31
#define BDOOR_CMD_EFI_SERIALCON_CONFIG 69 /* CPL 0 only. */
#define BDOOR_CMD_BUG328986 70 /* CPL 0 only. */
#define BDOOR_CMD_FIRMWARE_ERROR 71 /* CPL 0 only. */
# define BDOOR_CMD_FE_INSUFFICIENT_MEM 0
# define BDOOR_CMD_FE_EXCEPTION 1
#define BDOOR_CMD_VMK_INFO 72
#define BDOOR_CMD_EFI_BOOT_CONFIG 73 /* CPL 0 only. */
# define BDOOR_CMD_EBC_LEGACYBOOT_ENABLED 0
# define BDOOR_CMD_EBC_GET_ORDER 1
# define BDOOR_CMD_EBC_SHELL_ACTIVE 2
# define BDOOR_CMD_EBC_GET_NETWORK_BOOT_PROTOCOL 3
#define BDOOR_CMD_GET_HW_MODEL 74 /* CPL 0 only. */
#define BDOOR_CMD_GET_SVGA_CAPABILITIES 75 /* CPL 0 only. */
#define BDOOR_CMD_GET_FORCE_X2APIC 76 /* CPL 0 only */
#define BDOOR_CMD_SET_PCI_HOLE 77 /* CPL 0 only */
#define BDOOR_CMD_GET_PCI_HOLE 78 /* CPL 0 only */
#define BDOOR_CMD_GET_PCI_BAR 79 /* CPL 0 only */
#define BDOOR_CMD_SHOULD_GENERATE_SYSTEMID 80 /* CPL 0 only */
#define BDOOR_CMD_READ_DEBUG_FILE 81 /* Devel only. */
#define BDOOR_CMD_MAX 82
/*
* IMPORTANT NOTE: When modifying the behavior of an existing backdoor command,
* you must adhere to the semantics expected by the oldest Tools who use that
* command. Specifically, do not alter the way in which the command modifies
* the registers. Otherwise backwards compatibility will suffer.
*/
/* Processing mode for guest pshare hints (SENDPSHAREHINTS cmd) */
#define BDOOR_PSHARE_HINTS_ASYNC 0
#define BDOOR_PSHARE_HINTS_SYNC 1
#define BDOOR_PSHARE_HINTS_TYPE(ecx) (((ecx) >> 16) & 0x1)
/* Version of backdoor pshare hints protocol */
#define BDOOR_PSHARE_HINTS_VERSION 1
#define BDOOR_PSHARE_HINTS_VER(ecx) (((ecx) >> 17) & 0x7f)
/* Task applied to backdoor pshare hints */
#define BDOOR_PSHARE_HINTS_CMD_SHARE 0
#define BDOOR_PSHARE_HINTS_CMD_DROP 1
#define BDOOR_PSHARE_HINTS_CMD_MAX 2
#define BDOOR_PSHARE_HINTS_CMD(ecx) (((ecx) >> 24) & 0xff)
/* Nesting control operations */
#define NESTING_CONTROL_RESTRICT_BACKDOOR 0
#define NESTING_CONTROL_OPEN_BACKDOOR 1
#define NESTING_CONTROL_QUERY 2
#define NESTING_CONTROL_MAX 2
/* EFI Boot Order options, nibble-sized. */
#define EFI_BOOT_ORDER_TYPE_EFI 0x0
#define EFI_BOOT_ORDER_TYPE_LEGACY 0x1
#define EFI_BOOT_ORDER_TYPE_NONE 0xf
#define BDOOR_NETWORK_BOOT_PROTOCOL_NONE 0x0
#define BDOOR_NETWORK_BOOT_PROTOCOL_IPV4 0x1
#define BDOOR_NETWORK_BOOT_PROTOCOL_IPV6 0x2
/* High-bandwidth backdoor port. --hpreg */
#define BDOORHB_PORT 0x5659
#define BDOORHB_CMD_MESSAGE 0
#define BDOORHB_CMD_VASSERT 1
#define BDOORHB_CMD_MAX 2
/*
* There is another backdoor which allows access to certain TSC-related
* values using otherwise illegal PMC indices when the pseudo_perfctr
* control flag is set.
*/
#define BDOOR_PMC_HW_TSC 0x10000
#define BDOOR_PMC_REAL_NS 0x10001
#define BDOOR_PMC_APPARENT_NS 0x10002
#define BDOOR_PMC_PSEUDO_TSC 0x10003
#define IS_BDOOR_PMC(index) (((index) | 3) == 0x10003)
#define BDOOR_CMD(ecx) ((ecx) & 0xffff)
/* Sub commands for BDOOR_CMD_VMK_INFO */
#define BDOOR_CMD_VMK_INFO_ENTRY 1
#ifdef VMM
/*
*----------------------------------------------------------------------
*
* Backdoor_CmdRequiresFullyValidVCPU --
*
* A few backdoor commands require the full VCPU to be valid
* (including GDTR, IDTR, TR and LDTR). The rest get read/write
* access to GPRs and read access to Segment registers (selectors).
*
* Result:
* True iff VECX contains a command that require the full VCPU to
* be valid.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
Backdoor_CmdRequiresFullyValidVCPU(unsigned cmd)
{
return cmd == BDOOR_CMD_SIDT ||
cmd == BDOOR_CMD_SGDT ||
cmd == BDOOR_CMD_SLDT_STR;
}
#endif
#endif

View File

@@ -0,0 +1,132 @@
/*********************************************************
* Copyright (C) 1999-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* backdoor_types.h --
*
* Type definitions for backdoor interaction code.
*/
#ifndef _BACKDOOR_TYPES_H_
#define _BACKDOOR_TYPES_H_
#ifndef VM_I386
#error The backdoor protocol is only supported on x86 architectures.
#endif
/*
* These #defines are intended for defining register structs as part of
* existing named unions. If the union should encapsulate the register
* (and nothing else), use DECLARE_REG_NAMED_STRUCT defined below.
*/
#define DECLARE_REG32_STRUCT \
struct { \
uint16 low; \
uint16 high; \
} halfs; \
uint32 word
#define DECLARE_REG64_STRUCT \
DECLARE_REG32_STRUCT; \
struct { \
uint32 low; \
uint32 high; \
} words; \
uint64 quad
#ifndef VM_X86_64
#define DECLARE_REG_STRUCT DECLARE_REG32_STRUCT
#else
#define DECLARE_REG_STRUCT DECLARE_REG64_STRUCT
#endif
#define DECLARE_REG_NAMED_STRUCT(_r) \
union { DECLARE_REG_STRUCT; } _r
/*
* Some of the registers are expressed by semantic name, because if they were
* expressed as register structs declared above, we could only address them
* by fixed size (half-word, word, quad, etc.) instead of by varying size
* (size_t, uintptr_t).
*
* To be cleaner, these registers are expressed ONLY by semantic name,
* rather than by a union of the semantic name and a register struct.
*/
typedef union {
struct {
DECLARE_REG_NAMED_STRUCT(ax);
size_t size; /* Register bx. */
DECLARE_REG_NAMED_STRUCT(cx);
DECLARE_REG_NAMED_STRUCT(dx);
DECLARE_REG_NAMED_STRUCT(si);
DECLARE_REG_NAMED_STRUCT(di);
} in;
struct {
DECLARE_REG_NAMED_STRUCT(ax);
DECLARE_REG_NAMED_STRUCT(bx);
DECLARE_REG_NAMED_STRUCT(cx);
DECLARE_REG_NAMED_STRUCT(dx);
DECLARE_REG_NAMED_STRUCT(si);
DECLARE_REG_NAMED_STRUCT(di);
} out;
} Backdoor_proto;
typedef union {
struct {
DECLARE_REG_NAMED_STRUCT(ax);
DECLARE_REG_NAMED_STRUCT(bx);
size_t size; /* Register cx. */
DECLARE_REG_NAMED_STRUCT(dx);
uintptr_t srcAddr; /* Register si. */
uintptr_t dstAddr; /* Register di. */
DECLARE_REG_NAMED_STRUCT(bp);
} in;
struct {
DECLARE_REG_NAMED_STRUCT(ax);
DECLARE_REG_NAMED_STRUCT(bx);
DECLARE_REG_NAMED_STRUCT(cx);
DECLARE_REG_NAMED_STRUCT(dx);
DECLARE_REG_NAMED_STRUCT(si);
DECLARE_REG_NAMED_STRUCT(di);
DECLARE_REG_NAMED_STRUCT(bp);
} out;
} Backdoor_proto_hb;
MY_ASSERTS(BACKDOOR_STRUCT_SIZES,
ASSERT_ON_COMPILE(sizeof(Backdoor_proto) == 6 * sizeof(uintptr_t));
ASSERT_ON_COMPILE(sizeof(Backdoor_proto_hb) == 7 * sizeof(uintptr_t));
)
#undef DECLARE_REG_STRUCT
#endif /* _BACKDOOR_TYPES_H_ */

View File

@@ -0,0 +1,69 @@
/*********************************************************
* Copyright (C) 2009-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* community_source.h --
*
* Macros for excluding source code from community.
*/
#ifndef _COMMUNITY_SOURCE_H_
#define _COMMUNITY_SOURCE_H_
/*
* Convenience macro for COMMUNITY_SOURCE
*/
#undef EXCLUDE_COMMUNITY_SOURCE
#ifdef COMMUNITY_SOURCE
#define EXCLUDE_COMMUNITY_SOURCE(x)
#else
#define EXCLUDE_COMMUNITY_SOURCE(x) x
#endif
#undef COMMUNITY_SOURCE_AMD_SECRET
#if !defined(COMMUNITY_SOURCE) || defined(AMD_SOURCE)
/*
* It's ok to include AMD_SECRET source code for non-Community Source,
* or for drops directed at AMD.
*/
#define COMMUNITY_SOURCE_AMD_SECRET
#endif
#undef COMMUNITY_SOURCE_INTEL_SECRET
#if !defined(COMMUNITY_SOURCE) || defined(INTEL_SOURCE)
/*
* It's ok to include INTEL_SECRET source code for non-Community Source,
* or for drops directed at Intel.
*/
#define COMMUNITY_SOURCE_INTEL_SECRET
#endif
#endif

View File

@@ -0,0 +1,88 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
#ifndef _CPUID_INFO_H
#define _CPUID_INFO_H
#include "vm_basic_asm.h"
#include "x86cpuid_asm.h"
typedef struct CPUID0 {
int numEntries;
char name[16]; // 4 extra bytes to null terminate
} CPUID0;
typedef struct CPUID1 {
uint32 version;
uint32 ebx;
uint32 ecxFeatures;
uint32 edxFeatures;
} CPUID1;
typedef struct CPUID80 {
uint32 numEntries;
uint32 ebx;
uint32 ecx;
uint32 edx;
} CPUID80;
typedef struct CPUID81 {
uint32 eax;
uint32 ebx;
uint32 ecxFeatures;
uint32 edxFeatures;
} CPUID81;
typedef struct CPUIDSummary {
CPUID0 id0;
CPUID1 id1;
CPUIDRegs ida;
CPUID80 id80;
CPUID81 id81;
CPUIDRegs id88, id8a;
} CPUIDSummary;
/*
*----------------------------------------------------------------------
*
* CPUIDSummary_RegsFromCpuid0 --
*
* Fills in the given CPUIDRegs struct with the values from the CPUID0 struct.
*
* Results:
* Returns the CPUIDRegs pointer passed in.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE CPUIDRegs*
CPUIDSummary_RegsFromCpuid0(CPUID0* id0In,
CPUIDRegs* id0Out)
{
id0Out->eax = id0In->numEntries;
id0Out->ebx = *(uint32 *) (id0In->name + 0);
id0Out->edx = *(uint32 *) (id0In->name + 4);
id0Out->ecx = *(uint32 *) (id0In->name + 8);
return id0Out;
}
#endif

View File

@@ -0,0 +1,34 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* debug.h --
*
* Platform specific debug routines
*
*/
#ifndef __DEBUG_H__
# define __DEBUG_H__
# include "vm_basic_types.h"
void Debug(char const *fmt, ...) PRINTF_DECL(1, 2);
#endif /* __DEBUG_H__ */

View File

@@ -0,0 +1,236 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* dynbuf.h --
*
* Dynamic buffers
*/
#ifndef __DYNBUF_H__
# define __DYNBUF_H__
#include <string.h>
#include "vm_basic_types.h"
#include "vm_assert.h"
typedef struct DynBuf {
char *data;
size_t size;
size_t allocated;
} DynBuf;
void
DynBuf_Init(DynBuf *b); // IN
void
DynBuf_Destroy(DynBuf *b); // IN
void *
DynBuf_AllocGet(DynBuf const *b); // IN
void
DynBuf_Attach(DynBuf *b, // IN
size_t size, // IN
void *data); // IN
void *
DynBuf_Detach(DynBuf *b); // IN
Bool
DynBuf_Enlarge(DynBuf *b, // IN
size_t min_size); // IN
Bool
DynBuf_Append(DynBuf *b, // IN
void const *data, // IN
size_t size); // IN
Bool
DynBuf_Trim(DynBuf *b); // IN
Bool
DynBuf_Copy(DynBuf *src, // IN
DynBuf *dest); // OUT
void
DynBuf_SafeInternalAppend(DynBuf *b, // IN
void const *data, // IN
size_t size, // IN
char const *file, // IN
unsigned int lineno); // IN
#define DynBuf_SafeAppend(_buf, _data, _size) \
DynBuf_SafeInternalAppend(_buf, _data, _size, __FILE__, __LINE__)
/*
*-----------------------------------------------------------------------------
*
* DynBuf_Get --
*
* Retrieve a pointer to the data contained in a dynamic buffer --hpreg
*
* Results:
* The pointer to the data
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
#if defined(SWIG)
static void *
#else
static INLINE void *
#endif
DynBuf_Get(DynBuf const *b) // IN
{
ASSERT(b);
return b->data;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_GetSize --
*
* Returns the current size of the dynamic buffer --hpreg
*
* Results:
* The current size of the dynamic buffer
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
#if defined(SWIG)
static size_t
#else
static INLINE size_t
#endif
DynBuf_GetSize(DynBuf const *b) // IN
{
ASSERT(b);
return b->size;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_SetSize --
*
* Set the current size of a dynamic buffer --hpreg
*
* Results:
* None
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
#if defined(SWIG)
static void
#else
static INLINE void
#endif
DynBuf_SetSize(DynBuf *b, // IN
size_t size) // IN
{
ASSERT(b);
ASSERT(size <= b->allocated);
b->size = size;
}
/*
*-----------------------------------------------------------------------------
*
* DynBuf_GetAllocatedSize --
*
* Returns the current allocated size of the dynamic buffer --hpreg
*
* Results:
* The current allocated size of the dynamic buffer
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
#if defined(SWIG)
static size_t
#else
static INLINE size_t
#endif
DynBuf_GetAllocatedSize(DynBuf const *b) // IN
{
ASSERT(b);
return b->allocated;
}
/*
*----------------------------------------------------------------------------
*
* DynBuf_AppendString --
*
* Append the string to the specified DynBuf object. Basically a
* fancy strcat().
*
* Results:
* TRUE on success
* FALSE on failure (not enough memory)
*
*
* Side effects:
* DynBuf may change its size or allocate additional memory.
*
*----------------------------------------------------------------------------
*/
#if defined(SWIG)
static Bool
#else
static INLINE Bool
#endif
DynBuf_AppendString(DynBuf *buf, // IN
const char *string) // IN
{
/*
* Make sure to copy the NULL.
*/
return DynBuf_Append(buf, string, strlen(string) + 1);
}
#endif /* __DYNBUF_H__ */

View File

@@ -0,0 +1,100 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* guest_msg_def.h --
*
* Second layer of the internal communication channel between guest
* applications and vmware
*
*/
#ifndef _GUEST_MSG_DEF_H_
#define _GUEST_MSG_DEF_H_
/* Basic request types */
typedef enum {
MESSAGE_TYPE_OPEN,
MESSAGE_TYPE_SENDSIZE,
MESSAGE_TYPE_SENDPAYLOAD,
MESSAGE_TYPE_RECVSIZE,
MESSAGE_TYPE_RECVPAYLOAD,
MESSAGE_TYPE_RECVSTATUS,
MESSAGE_TYPE_CLOSE,
} MessageType;
/* Reply statuses */
/* The basic request succeeded */
#define MESSAGE_STATUS_SUCCESS 0x0001
/* vmware has a message available for its party */
#define MESSAGE_STATUS_DORECV 0x0002
/* The channel has been closed */
#define MESSAGE_STATUS_CLOSED 0x0004
/* vmware removed the message before the party fetched it */
#define MESSAGE_STATUS_UNSENT 0x0008
/* A checkpoint occurred */
#define MESSAGE_STATUS_CPT 0x0010
/* An underlying device is powering off */
#define MESSAGE_STATUS_POWEROFF 0x0020
/* vmware has detected a timeout on the channel */
#define MESSAGE_STATUS_TIMEOUT 0x0040
/* vmware supports high-bandwidth for sending and receiving the payload */
#define MESSAGE_STATUS_HB 0x0080
/*
* This mask defines the status bits that the guest is allowed to set;
* we use this to mask out all other bits when receiving the status
* from the guest. Otherwise, the guest can manipulate VMX state by
* setting status bits that are only supposed to be changed by the
* VMX. See bug 45385.
*/
#define MESSAGE_STATUS_GUEST_MASK MESSAGE_STATUS_SUCCESS
/*
* Max number of channels.
* Unfortunately this has to be public because the monitor part
* of the backdoor needs it for its trivial-case optimization. [greg]
*/
#define GUESTMSG_MAX_CHANNEL 8
/* Flags to open a channel. --hpreg */
#define GUESTMSG_FLAG_COOKIE 0x80000000
#define GUESTMSG_FLAG_ALL GUESTMSG_FLAG_COOKIE
/*
* Maximum size of incoming message. This is to prevent denial of host service
* attacks from guest applications.
*/
#define GUESTMSG_MAX_IN_SIZE (64 * 1024)
#endif /* _GUEST_MSG_DEF_H_ */

View File

@@ -0,0 +1,36 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* hostType.h --
*
* Interface to host-specific information functions
*
*/
#ifndef _HOSTTYPE_H_
#define _HOSTTYPE_H_
#include "vm_basic_types.h"
Bool HostType_OSIsVMK(void);
Bool HostType_OSIsPureVMK(void);
Bool HostType_OSIsVMK64(void);
Bool HostType_OSIsSimulator(void);
#endif /* ifndef _HOSTTYPE_H_ */

View File

@@ -0,0 +1,234 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* hostinfo.h --
*
* Interface to host-specific information functions
*
*/
#if !defined(_HOSTINFO_H_)
#define _HOSTINFO_H_
#include "vm_basic_types.h"
#include "vm_basic_defs.h"
#include "x86cpuid.h"
#include "unicodeTypes.h"
typedef enum {
HOSTINFO_PROCESS_QUERY_DEAD, // Procss is dead (does not exist)
HOSTINFO_PROCESS_QUERY_ALIVE, // Process is alive (does exist)
HOSTINFO_PROCESS_QUERY_UNKNOWN // Process existence cannot be determined
} HostinfoProcessQuery;
HostinfoProcessQuery Hostinfo_QueryProcessExistence(int pid);
Unicode Hostinfo_NameGet(void); /* don't free result */
Unicode Hostinfo_HostName(void); /* free result */
void Hostinfo_MachineID(uint32 *hostNameHash,
uint64 *hostHardwareID);
Bool Hostinfo_GetMemoryInfoInPages(unsigned int *minSize,
unsigned int *maxSize,
unsigned int *currentSize);
#ifdef __linux__
Bool Hostinfo_GetSwapInfoInPages(unsigned int *totalSwap,
unsigned int *freeSwap);
#endif
Bool Hostinfo_GetRatedCpuMhz(int32 cpuNumber,
uint32 *mHz);
char *Hostinfo_GetCpuDescription(uint32 cpuNumber);
void Hostinfo_GetTimeOfDay(VmTimeType *time);
VmTimeType Hostinfo_SystemUpTime(void);
VmTimeType Hostinfo_SystemTimerNS(void);
static INLINE VmTimeType
Hostinfo_SystemTimerUS(void)
{
return Hostinfo_SystemTimerNS() / 1000ULL;
}
static INLINE VmTimeType
Hostinfo_SystemTimerMS(void)
{
return Hostinfo_SystemTimerNS() / 1000000ULL;
}
int Hostinfo_OSVersion(unsigned int i);
int Hostinfo_GetSystemBitness(void);
const char *Hostinfo_OSVersionString(void);
char *Hostinfo_GetOSName(void);
char *Hostinfo_GetOSGuestString(void);
Bool Hostinfo_OSIsSMP(void);
#if defined(_WIN32)
Bool Hostinfo_OSIsWinNT(void);
Bool Hostinfo_OSIsWow64(void);
Bool Hostinfo_TSCInvariant(void);
DWORD Hostinfo_OpenProcessBits(void);
DWORD Hostinfo_OpenThreadBits(void);
#else
void Hostinfo_ResetProcessState(const int *keepFds,
size_t numKeepFds);
int Hostinfo_Execute(const char *path,
char * const *args,
Bool wait,
const int *keepFds,
size_t numKeepFds);
typedef enum HostinfoDaemonizeFlags {
HOSTINFO_DAEMONIZE_DEFAULT = 0,
HOSTINFO_DAEMONIZE_NOCHDIR = (1 << 0),
HOSTINFO_DAEMONIZE_NOCLOSE = (1 << 1),
HOSTINFO_DAEMONIZE_EXIT = (1 << 2),
HOSTINFO_DAEMONIZE_LOCKPID = (1 << 3),
} HostinfoDaemonizeFlags;
Bool Hostinfo_Daemonize(const char *path,
char * const *args,
HostinfoDaemonizeFlags flags,
const char *pidPath,
const int *keepFds,
size_t numKeepFds);
#endif
Bool Hostinfo_NestingSupported(void);
Bool Hostinfo_VCPUInfoBackdoor(unsigned bit);
Bool Hostinfo_SLC64Supported(void);
Bool Hostinfo_SynchronizedVTSCs(void);
Bool Hostinfo_NestedHVReplaySupported(void);
Bool Hostinfo_TouchBackDoor(void);
Bool Hostinfo_TouchVirtualPC(void);
Bool Hostinfo_TouchXen(void);
char *Hostinfo_HypervisorCPUIDSig(void);
#define HGMP_PRIVILEGE 0
#define HGMP_NO_PRIVILEGE 1
Unicode Hostinfo_GetModulePath(uint32 priv);
char *Hostinfo_GetLibraryPath(void *addr);
Unicode Hostinfo_GetUser(void);
void Hostinfo_LogMemUsage(void);
/*
* HostInfoCpuIdInfo --
*
* Contains cpuid information for a CPU.
*/
typedef struct {
CpuidVendor vendor;
uint32 version;
uint8 family;
uint8 model;
uint8 stepping;
uint8 type;
uint32 features;
uint32 extfeatures;
} HostinfoCpuIdInfo;
uint32 Hostinfo_NumCPUs(void);
char *Hostinfo_GetCpuidStr(void);
Bool Hostinfo_GetCpuid(HostinfoCpuIdInfo *info);
#if !defined(VMX86_SERVER)
Bool Hostinfo_CPUCounts(uint32 *logical,
uint32 *cores,
uint32 *pkgs);
#endif
#if defined(_WIN32)
typedef enum {
OS_WIN95 = 1,
OS_WIN98 = 2,
OS_WINME = 3,
OS_WINNT = 4,
OS_WIN2K = 5,
OS_WINXP = 6,
OS_WIN2K3 = 7,
OS_VISTA = 8,
OS_WINSEVEN = 9,
OS_WIN8 = 10,
OS_WIN10 = 11,
OS_UNKNOWN = 99999 // last, highest value
} OS_TYPE;
typedef enum {
OS_DETAIL_WIN95 = 1,
OS_DETAIL_WIN98 = 2,
OS_DETAIL_WINME = 3,
OS_DETAIL_WINNT = 4,
OS_DETAIL_WIN2K = 5,
OS_DETAIL_WIN2K_PRO = 6,
OS_DETAIL_WIN2K_SERV = 7,
OS_DETAIL_WIN2K_ADV_SERV = 8,
OS_DETAIL_WINXP = 9,
OS_DETAIL_WINXP_HOME = 10,
OS_DETAIL_WINXP_PRO = 11,
OS_DETAIL_WINXP_X64_PRO = 12,
OS_DETAIL_WIN2K3 = 13,
OS_DETAIL_WIN2K3_WEB = 14,
OS_DETAIL_WIN2K3_ST = 15,
OS_DETAIL_WIN2K3_EN = 16,
OS_DETAIL_WIN2K3_BUS = 17,
OS_DETAIL_VISTA = 18,
OS_DETAIL_WIN2K8 = 19,
OS_DETAIL_WINSEVEN = 20,
OS_DETAIL_WIN2K8R2 = 21,
OS_DETAIL_WIN8 = 22,
OS_DETAIL_WIN8SERVER = 23,
OS_DETAIL_WIN10 = 24,
OS_DETAIL_WIN10SERVER = 25,
OS_DETAIL_UNKNOWN = 99999 // last, highest value
} OS_DETAIL_TYPE;
/* generic names (to protect the future) but Windows specific for now */
OS_TYPE Hostinfo_GetOSType(void);
OS_DETAIL_TYPE Hostinfo_GetOSDetailType(void);
Bool Hostinfo_GetPCFrequency(uint64 *pcHz);
Bool Hostinfo_GetMhzOfProcessor(int32 processorNumber,
uint32 *currentMhz,
uint32 *maxMhz);
uint64 Hostinfo_SystemIdleTime(void);
Bool Hostinfo_GetAllCpuid(CPUIDQuery *query);
static INLINE Bool
Hostinfo_AtLeastVista(void)
{
return (Hostinfo_GetOSType() >= OS_VISTA);
}
#endif
void Hostinfo_LogLoadAverage(void);
Bool Hostinfo_GetLoadAverage(uint32 *l);
#ifdef __APPLE__
size_t Hostinfo_GetKernelZoneElemSize(char const *name);
char *Hostinfo_GetHardwareModel(void);
#endif
#endif /* ifndef _HOSTINFO_H_ */

View File

@@ -0,0 +1,49 @@
/*********************************************************
* Copyright (C) 2009-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* hostinfoInt.h --
*
* lib/misc Hostinfo_* private declarations.
*/
#ifndef _HOSTINFOINT_H_
#define _HOSTINFOINT_H_
#define MAX_OS_NAME_LEN 128
#define MAX_OS_FULLNAME_LEN 512
/*
* Global variables
*/
extern volatile Bool HostinfoOSNameCacheValid;
extern char HostinfoCachedOSName[MAX_OS_NAME_LEN];
extern char HostinfoCachedOSFullName[MAX_OS_FULLNAME_LEN];
/*
* Global functions
*/
extern Bool HostinfoOSData(void);
#endif // ifndef _HOSTINFOINT_H_

View File

@@ -0,0 +1,72 @@
/*********************************************************
* Copyright (C) 1999-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* message.h --
*
* Second layer of the internal communication channel between guest
* applications and vmware
*/
#ifndef __MESSAGE_H__
# define __MESSAGE_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "vm_basic_types.h"
typedef struct Message_Channel Message_Channel;
Message_Channel *
Message_Open(uint32 proto); // IN
Bool
Message_Send(Message_Channel *chan, // IN/OUT
const unsigned char *buf, // IN
size_t bufSize); // IN
Bool
Message_Receive(Message_Channel *chan, // IN/OUT
unsigned char **buf, // OUT
size_t *bufSize); // OUT
Bool
Message_Close(Message_Channel *chan); // IN/OUT
#ifdef __cplusplus
}
#endif
#endif /* __MESSAGE_H__ */

View File

@@ -0,0 +1,143 @@
/*********************************************************
* Copyright (C) 2003-2014 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* mul64.h
*
* Integer by fixed point multiplication, with rounding.
*
* These routines are implemented in assembly language for most
* supported platforms. This file has plain C fallback versions.
*/
#ifndef _MUL64_H_
#define _MUL64_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#include "includeCheck.h"
#include "vm_basic_asm.h"
#ifdef MUL64_NO_ASM
/*
*-----------------------------------------------------------------------------
*
* Mul64x3264 --
*
* Unsigned integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Unsigned 64-bit integer multiplicand.
* Unsigned 32-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Unsigned 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
static INLINE uint64
Mul64x3264(uint64 multiplicand, uint32 multiplier, uint32 shift)
{
uint64 lo, hi, lo2, hi2;
unsigned carry;
// ASSERT(shift >= 0 && shift < 64);
lo = (multiplicand & 0xffffffff) * multiplier;
hi = (multiplicand >> 32) * multiplier;
lo2 = lo + (hi << 32);
carry = lo2 < lo;
hi2 = (hi >> 32) + carry;
if (shift == 0) {
return lo2;
} else {
return (lo2 >> shift) + (hi2 << (64 - shift)) +
((lo2 >> (shift - 1)) & 1);
}
}
/*
*-----------------------------------------------------------------------------
*
* Muls64x32s64 --
*
* Signed integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Signed 64-bit integer multiplicand.
* Unsigned 32-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Signed 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
static INLINE int64
Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
{
uint64 lo, hi, lo2, hi2;
unsigned carry;
// ASSERT(shift >= 0 && shift < 64);
hi = ((uint64)multiplicand >> 32) * multiplier;
if (multiplicand < 0) {
hi -= (uint64)multiplier << 32;
}
lo = ((uint64)multiplicand & 0xffffffff) * multiplier;
lo2 = lo + (hi << 32);
carry = lo2 < lo;
hi2 = (((int64)hi >> 32) + carry);
if (shift == 0) {
return lo2;
} else {
return (lo2 >> shift) + (hi2 << (64 - shift)) +
((lo2 >> (shift - 1)) & 1);
}
}
#endif
#endif // _MUL64_NOASM_H_

View File

@@ -0,0 +1,187 @@
/*********************************************************
* Copyright (C) 2004-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* safetime.h --
*
* This header file defines wrappers so that we use the
* 64-bit versions of the C time calls. This file is
* temporary until we switch to a newer version of
* Visual Studio that uses the 64-bit verisions by default.
*
* In Windows, the user is allowed to set the time past the
* 32-bit overflow date (in 2038), which can cause crashes
* and security problems. In Linux, the time can't be set
* to overflow, so we do nothing.
*
* NB: We do not know if one can set the time past 2038 in
* 64-bit versions of Linux, and, if so, what happens when
* one does. This requires further investigation sometime
* in the future.
*
* The stat types and functions must be defined manually,
* since they contain time_ts, and we can't use the macro
* trick, since the struct stat and the function stat have
* the same 32 bit name (but different 64 bit names).
*
*/
#ifndef _SAFETIME_H_
#define _SAFETIME_H_
#ifdef _WIN32
#undef FMTTIME
#define FMTTIME FMT64"d"
#if (_MSC_VER < 1400)
#if (defined(_STAT_DEFINED) || defined(_INC_TIME) || defined(_INC_TYPES))
#error Use safetime.h instead of time.h, stat.h, and types.h
#endif
#define _STAT_DEFINED
#include <time.h>
#include <sys/utime.h>
#include <sys/timeb.h>
#define time_t __time64_t
#define time(a) _time64(a)
#define localtime(a) _localtime64((a))
#define _ctime(a) _ctime64((a))
#define ctime(a) _ctime64((a))
#define _ftime(a) _ftime64((a))
#define ftime(a) _ftime64((a))
#define _timeb __timeb64
#define _gmtime(a) _gmtime64((a))
#define gmtime(a) _gmtime64((a))
#define _mktime(a) _mktime64((a))
#define mktime(a) _mktime64((a))
#define _utime(a,b) _utime64((a),(b))
#define utime(a,b) _utime64((a),(b))
#define _utimbuf __utimbuf64
#define utimbuf __utimbuf64
#define _wctime(a) _wctime64((a),(b))
#define wctime(a) _wctime64((a),(b))
#define _futime(a,b) _futime64((a),(b))
#define futime(a,b) _futime64((a),(b))
#define _wutime(a,b) _wutime64((a),(b))
#define wutime(a,b) _wutime64((a),(b))
#include <sys/types.h>
#ifdef _MSC_VER
#pragma pack(push,8)
#endif
struct _stat {
_dev_t st_dev;
_ino_t st_ino;
unsigned short st_mode;
short st_nlink;
short st_uid;
short st_gid;
_dev_t st_rdev;
__int64 st_size;
__time64_t st_atime;
__time64_t st_mtime;
__time64_t st_ctime;
};
struct stat {
_dev_t st_dev;
_ino_t st_ino;
unsigned short st_mode;
short st_nlink;
short st_uid;
short st_gid;
_dev_t st_rdev;
__int64 st_size;
__time64_t st_atime;
__time64_t st_mtime;
__time64_t st_ctime;
};
struct __stat64 {
_dev_t st_dev;
_ino_t st_ino;
unsigned short st_mode;
short st_nlink;
short st_uid;
short st_gid;
_dev_t st_rdev;
__int64 st_size;
__time64_t st_atime;
__time64_t st_mtime;
__time64_t st_ctime;
};
#ifdef _MSC_VER
#pragma pack(pop)
#endif
#include <sys/stat.h>
#define stat(a,b) _stat64((a),(struct __stat64*)(b))
#define _stat(a,b) _stat64((a),(struct __stat64*)(b))
#define fstat(a,b) _fstat64((a),(struct __stat64*)(b))
#define _fstat(a,b) _fstat64((a),(struct __stat64*)(b))
#define wstat(a,b) _wstat64((a),(struct __stat64*)(b))
#define _wstat(a,b) _wstat64((a),(struct __stat64*)(b))
#else /* (_MSC_VER < 1400) */
/*
* Starting with VC80, we can pick between 32-bit and 64-bit time_t
* by defining or not defining _USE_32BIT_TIME_T. Don't define it.
*/
#include <time.h>
#include <sys/utime.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
/* Make sure that the headers didn't revert to 32-bit. */
#ifdef _USE_32BIT_TIME_T
#error Refusing to use 32-bit time_t in safetime.h
#endif
#endif /* (_MSC_VER < 1400) */
#else
#include <sys/types.h>
#include <time.h>
#include <sys/stat.h>
#include <utime.h>
#endif
#endif

View File

@@ -0,0 +1,485 @@
/*********************************************************
* Copyright (C) 2007-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* unicodeTypes.h --
*
* Types used throughout the Unicode library.
*/
#ifndef _UNICODE_TYPES_H_
#define _UNICODE_TYPES_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "vm_basic_types.h"
#include "vm_assert.h"
#if defined(SUPPORT_UNICODE_OPAQUE)
/*
* To assist with finding code that hasn't been internationalized, we
* support building with an opaque Unicode type. This catches users
* passing a char * of unknown encoding to Unicode functions, and
* assigning a Unicode to a char *.
*/
typedef struct UnicodeImpl UnicodeImpl;
typedef UnicodeImpl * Unicode;
typedef const UnicodeImpl * ConstUnicode;
#else
/*
* As a transitionary development tactic to prevent code churn while the
* Unicode libraries are being developed, we'll start with a simple
* implementation of Unicode as UTF-8 char *.
*/
typedef char * Unicode;
typedef const char * ConstUnicode;
#endif
typedef ssize_t UnicodeIndex;
/*
* Special UnicodeIndex value returned when a string is not found.
*/
enum {
UNICODE_INDEX_NOT_FOUND = -1
};
/*
* Encodings passed to convert encoded byte strings to and from
* Unicode.
*
* Keep this enum synchronized with ICU_ENCODING_LIST in unicodeICU.cc!
*/
typedef enum {
STRING_ENCODING_FIRST,
/*
* Byte string encodings that support all characters in Unicode.
*
* If you don't know what to use for bytes in a new system, use
* STRING_ENCODING_UTF8.
*/
STRING_ENCODING_UTF8 = STRING_ENCODING_FIRST,
STRING_ENCODING_UTF16_LE, // Little-endian UTF-16.
STRING_ENCODING_UTF16_BE, // Big-endian UTF-16.
STRING_ENCODING_UTF16_XE, // UTF-16 with BOM.
STRING_ENCODING_UTF32_LE, // Little-endian UTF-32.
STRING_ENCODING_UTF32_BE, // Big-endian UTF-32.
STRING_ENCODING_UTF32_XE, // UTF-32 with BOM.
/*
* Legacy byte string encodings that only support a subset of Unicode.
*/
/*
* Latin encodings
*/
STRING_ENCODING_US_ASCII,
STRING_ENCODING_ISO_8859_1,
STRING_ENCODING_ISO_8859_2,
STRING_ENCODING_ISO_8859_3,
STRING_ENCODING_ISO_8859_4,
STRING_ENCODING_ISO_8859_5,
STRING_ENCODING_ISO_8859_6,
STRING_ENCODING_ISO_8859_7,
STRING_ENCODING_ISO_8859_8,
STRING_ENCODING_ISO_8859_9,
STRING_ENCODING_ISO_8859_10,
// ISO-8859-11 is unused.
// Oddly, there is no ISO-8859-12.
STRING_ENCODING_ISO_8859_13,
STRING_ENCODING_ISO_8859_14,
STRING_ENCODING_ISO_8859_15,
/*
* Chinese encodings
*/
STRING_ENCODING_GB_18030,
STRING_ENCODING_BIG_5,
STRING_ENCODING_BIG_5_HK,
STRING_ENCODING_GBK,
STRING_ENCODING_GB_2312,
STRING_ENCODING_ISO_2022_CN,
/*
* Japanese encodings
*/
STRING_ENCODING_SHIFT_JIS,
STRING_ENCODING_EUC_JP,
STRING_ENCODING_ISO_2022_JP,
STRING_ENCODING_ISO_2022_JP_1,
STRING_ENCODING_ISO_2022_JP_2,
/*
* Korean encodings
*/
STRING_ENCODING_ISO_2022_KR,
/*
* Windows encodings
*/
STRING_ENCODING_WINDOWS_1250,
STRING_ENCODING_WINDOWS_1251,
STRING_ENCODING_WINDOWS_1252,
STRING_ENCODING_WINDOWS_1253,
STRING_ENCODING_WINDOWS_1254,
STRING_ENCODING_WINDOWS_1255,
STRING_ENCODING_WINDOWS_1256,
STRING_ENCODING_WINDOWS_1257,
STRING_ENCODING_WINDOWS_1258,
STRING_ENCODING_ISO_6937_2_ADD,
STRING_ENCODING_JIS_X0201,
STRING_ENCODING_JIS_ENCODING,
STRING_ENCODING_EXTENDED_UNIX_CODE_FIXED_WIDTH_FOR_JAPANESE,
STRING_ENCODING_BS_4730,
STRING_ENCODING_SEN_850200_C,
STRING_ENCODING_IT,
STRING_ENCODING_ES,
STRING_ENCODING_DIN_66003,
STRING_ENCODING_NS_4551_1,
STRING_ENCODING_NF_Z_62_010,
STRING_ENCODING_ISO_10646_UTF_1,
STRING_ENCODING_ISO_646_BASIC_1983,
STRING_ENCODING_INVARIANT,
STRING_ENCODING_ISO_646_IRV_1983,
STRING_ENCODING_NATS_SEFI,
STRING_ENCODING_NATS_SEFI_ADD,
STRING_ENCODING_NATS_DANO,
STRING_ENCODING_NATS_DANO_ADD,
STRING_ENCODING_SEN_850200_B,
STRING_ENCODING_KS_C_5601_1987,
STRING_ENCODING_JIS_C6220_1969_JP,
STRING_ENCODING_JIS_C6220_1969_RO,
STRING_ENCODING_PT,
STRING_ENCODING_GREEK7_OLD,
STRING_ENCODING_LATIN_GREEK,
STRING_ENCODING_NF_Z_62_010__1973_,
STRING_ENCODING_LATIN_GREEK_1,
STRING_ENCODING_ISO_5427,
STRING_ENCODING_JIS_C6226_1978,
STRING_ENCODING_BS_VIEWDATA,
STRING_ENCODING_INIS,
STRING_ENCODING_INIS_8,
STRING_ENCODING_INIS_CYRILLIC,
STRING_ENCODING_ISO_5427_1981,
STRING_ENCODING_ISO_5428_1980,
STRING_ENCODING_GB_1988_80,
STRING_ENCODING_GB_2312_80,
STRING_ENCODING_NS_4551_2,
STRING_ENCODING_VIDEOTEX_SUPPL,
STRING_ENCODING_PT2,
STRING_ENCODING_ES2,
STRING_ENCODING_MSZ_7795_3,
STRING_ENCODING_JIS_C6226_1983,
STRING_ENCODING_GREEK7,
STRING_ENCODING_ASMO_449,
STRING_ENCODING_ISO_IR_90,
STRING_ENCODING_JIS_C6229_1984_A,
STRING_ENCODING_JIS_C6229_1984_B,
STRING_ENCODING_JIS_C6229_1984_B_ADD,
STRING_ENCODING_JIS_C6229_1984_HAND,
STRING_ENCODING_JIS_C6229_1984_HAND_ADD,
STRING_ENCODING_JIS_C6229_1984_KANA,
STRING_ENCODING_ISO_2033_1983,
STRING_ENCODING_ANSI_X3_110_1983,
STRING_ENCODING_T_61_7BIT,
STRING_ENCODING_T_61_8BIT,
STRING_ENCODING_ECMA_CYRILLIC,
STRING_ENCODING_CSA_Z243_4_1985_1,
STRING_ENCODING_CSA_Z243_4_1985_2,
STRING_ENCODING_CSA_Z243_4_1985_GR,
STRING_ENCODING_ISO_8859_6_E,
STRING_ENCODING_ISO_8859_6_I,
STRING_ENCODING_T_101_G2,
STRING_ENCODING_ISO_8859_8_E,
STRING_ENCODING_ISO_8859_8_I,
STRING_ENCODING_CSN_369103,
STRING_ENCODING_JUS_I_B1_002,
STRING_ENCODING_IEC_P27_1,
STRING_ENCODING_JUS_I_B1_003_SERB,
STRING_ENCODING_JUS_I_B1_003_MAC,
STRING_ENCODING_GREEK_CCITT,
STRING_ENCODING_NC_NC00_10_81,
STRING_ENCODING_ISO_6937_2_25,
STRING_ENCODING_GOST_19768_74,
STRING_ENCODING_ISO_8859_SUPP,
STRING_ENCODING_ISO_10367_BOX,
STRING_ENCODING_LATIN_LAP,
STRING_ENCODING_JIS_X0212_1990,
STRING_ENCODING_DS_2089,
STRING_ENCODING_US_DK,
STRING_ENCODING_DK_US,
STRING_ENCODING_KSC5636,
STRING_ENCODING_UNICODE_1_1_UTF_7,
STRING_ENCODING_ISO_2022_CN_EXT,
STRING_ENCODING_ISO_8859_16,
STRING_ENCODING_OSD_EBCDIC_DF04_15,
STRING_ENCODING_OSD_EBCDIC_DF03_IRV,
STRING_ENCODING_OSD_EBCDIC_DF04_1,
STRING_ENCODING_ISO_11548_1,
STRING_ENCODING_KZ_1048,
STRING_ENCODING_ISO_10646_UCS_2,
STRING_ENCODING_ISO_10646_UCS_4,
STRING_ENCODING_ISO_10646_UCS_BASIC,
STRING_ENCODING_ISO_10646_UNICODE_LATIN1,
STRING_ENCODING_ISO_10646_J_1,
STRING_ENCODING_ISO_UNICODE_IBM_1261,
STRING_ENCODING_ISO_UNICODE_IBM_1268,
STRING_ENCODING_ISO_UNICODE_IBM_1276,
STRING_ENCODING_ISO_UNICODE_IBM_1264,
STRING_ENCODING_ISO_UNICODE_IBM_1265,
STRING_ENCODING_UNICODE_1_1,
STRING_ENCODING_SCSU,
STRING_ENCODING_UTF_7,
STRING_ENCODING_CESU_8,
STRING_ENCODING_BOCU_1,
STRING_ENCODING_ISO_8859_1_WINDOWS_3_0_LATIN_1,
STRING_ENCODING_ISO_8859_1_WINDOWS_3_1_LATIN_1,
STRING_ENCODING_ISO_8859_2_WINDOWS_LATIN_2,
STRING_ENCODING_ISO_8859_9_WINDOWS_LATIN_5,
STRING_ENCODING_HP_ROMAN8,
STRING_ENCODING_ADOBE_STANDARD_ENCODING,
STRING_ENCODING_VENTURA_US,
STRING_ENCODING_VENTURA_INTERNATIONAL,
STRING_ENCODING_DEC_MCS,
STRING_ENCODING_IBM_850,
STRING_ENCODING_PC8_DANISH_NORWEGIAN,
STRING_ENCODING_IBM_862,
STRING_ENCODING_PC8_TURKISH,
STRING_ENCODING_IBM_SYMBOLS,
STRING_ENCODING_IBM_THAI,
STRING_ENCODING_HP_LEGAL,
STRING_ENCODING_HP_PI_FONT,
STRING_ENCODING_HP_MATH8,
STRING_ENCODING_ADOBE_SYMBOL_ENCODING,
STRING_ENCODING_HP_DESKTOP,
STRING_ENCODING_VENTURA_MATH,
STRING_ENCODING_MICROSOFT_PUBLISHING,
STRING_ENCODING_WINDOWS_31J,
STRING_ENCODING_MACINTOSH,
STRING_ENCODING_IBM_037,
STRING_ENCODING_IBM_038,
STRING_ENCODING_IBM_273,
STRING_ENCODING_IBM_274,
STRING_ENCODING_IBM_275,
STRING_ENCODING_IBM_277,
STRING_ENCODING_IBM_278,
STRING_ENCODING_IBM_280,
STRING_ENCODING_IBM_281,
STRING_ENCODING_IBM_284,
STRING_ENCODING_IBM_285,
STRING_ENCODING_IBM_290,
STRING_ENCODING_IBM_297,
STRING_ENCODING_IBM_420,
STRING_ENCODING_IBM_423,
STRING_ENCODING_IBM_424,
STRING_ENCODING_IBM_437,
STRING_ENCODING_IBM_500,
STRING_ENCODING_IBM_851,
STRING_ENCODING_IBM_852,
STRING_ENCODING_IBM_855,
STRING_ENCODING_IBM_857,
STRING_ENCODING_IBM_860,
STRING_ENCODING_IBM_861,
STRING_ENCODING_IBM_863,
STRING_ENCODING_IBM_864,
STRING_ENCODING_IBM_865,
STRING_ENCODING_IBM_868,
STRING_ENCODING_IBM_869,
STRING_ENCODING_IBM_870,
STRING_ENCODING_IBM_871,
STRING_ENCODING_IBM_880,
STRING_ENCODING_IBM_891,
STRING_ENCODING_IBM_903,
STRING_ENCODING_IBM_904,
STRING_ENCODING_IBM_905,
STRING_ENCODING_IBM_918,
STRING_ENCODING_IBM_1026,
STRING_ENCODING_EBCDIC_AT_DE,
STRING_ENCODING_EBCDIC_AT_DE_A,
STRING_ENCODING_EBCDIC_CA_FR,
STRING_ENCODING_EBCDIC_DK_NO,
STRING_ENCODING_EBCDIC_DK_NO_A,
STRING_ENCODING_EBCDIC_FI_SE,
STRING_ENCODING_EBCDIC_FI_SE_A,
STRING_ENCODING_EBCDIC_FR,
STRING_ENCODING_EBCDIC_IT,
STRING_ENCODING_EBCDIC_PT,
STRING_ENCODING_EBCDIC_ES,
STRING_ENCODING_EBCDIC_ES_A,
STRING_ENCODING_EBCDIC_ES_S,
STRING_ENCODING_EBCDIC_UK,
STRING_ENCODING_EBCDIC_US,
STRING_ENCODING_UNKNOWN_8BIT,
STRING_ENCODING_MNEMONIC,
STRING_ENCODING_MNEM,
STRING_ENCODING_VISCII,
STRING_ENCODING_VIQR,
STRING_ENCODING_KOI8_R,
STRING_ENCODING_HZ_GB_2312,
STRING_ENCODING_IBM_866,
STRING_ENCODING_IBM_775,
STRING_ENCODING_KOI8_U,
STRING_ENCODING_IBM_00858,
STRING_ENCODING_IBM_00924,
STRING_ENCODING_IBM_01140,
STRING_ENCODING_IBM_01141,
STRING_ENCODING_IBM_01142,
STRING_ENCODING_IBM_01143,
STRING_ENCODING_IBM_01144,
STRING_ENCODING_IBM_01145,
STRING_ENCODING_IBM_01146,
STRING_ENCODING_IBM_01147,
STRING_ENCODING_IBM_01148,
STRING_ENCODING_IBM_01149,
STRING_ENCODING_IBM_1047,
STRING_ENCODING_PTCP154,
STRING_ENCODING_AMIGA_1251,
STRING_ENCODING_KOI7_SWITCHED,
STRING_ENCODING_BRF,
STRING_ENCODING_TSCII,
STRING_ENCODING_TIS_620,
STRING_ENCODING_WINDOWS_709,
STRING_ENCODING_WINDOWS_710,
STRING_ENCODING_WINDOWS_720,
STRING_ENCODING_WINDOWS_737,
STRING_ENCODING_WINDOWS_875,
STRING_ENCODING_WINDOWS_1361,
STRING_ENCODING_WINDOWS_10000,
STRING_ENCODING_WINDOWS_10001,
STRING_ENCODING_WINDOWS_10002,
STRING_ENCODING_WINDOWS_10003,
STRING_ENCODING_WINDOWS_10004,
STRING_ENCODING_WINDOWS_10005,
STRING_ENCODING_WINDOWS_10006,
STRING_ENCODING_WINDOWS_10007,
STRING_ENCODING_WINDOWS_10008,
STRING_ENCODING_WINDOWS_10010,
STRING_ENCODING_WINDOWS_10017,
STRING_ENCODING_WINDOWS_10021,
STRING_ENCODING_WINDOWS_10029,
STRING_ENCODING_WINDOWS_10079,
STRING_ENCODING_WINDOWS_10081,
STRING_ENCODING_WINDOWS_10082,
STRING_ENCODING_WINDOWS_20000,
STRING_ENCODING_WINDOWS_20001,
STRING_ENCODING_WINDOWS_20002,
STRING_ENCODING_WINDOWS_20003,
STRING_ENCODING_WINDOWS_20004,
STRING_ENCODING_WINDOWS_20005,
STRING_ENCODING_WINDOWS_20105,
STRING_ENCODING_WINDOWS_20106,
STRING_ENCODING_WINDOWS_20107,
STRING_ENCODING_WINDOWS_20108,
STRING_ENCODING_WINDOWS_20269,
STRING_ENCODING_WINDOWS_20833,
STRING_ENCODING_WINDOWS_20949,
STRING_ENCODING_WINDOWS_21025,
STRING_ENCODING_WINDOWS_21027,
STRING_ENCODING_WINDOWS_29001,
STRING_ENCODING_WINDOWS_38598,
STRING_ENCODING_WINDOWS_50221,
STRING_ENCODING_WINDOWS_50222,
STRING_ENCODING_WINDOWS_50229,
STRING_ENCODING_WINDOWS_50930,
STRING_ENCODING_WINDOWS_50931,
STRING_ENCODING_WINDOWS_50933,
STRING_ENCODING_WINDOWS_50935,
STRING_ENCODING_WINDOWS_50936,
STRING_ENCODING_WINDOWS_50937,
STRING_ENCODING_WINDOWS_50939,
STRING_ENCODING_WINDOWS_51936,
STRING_ENCODING_WINDOWS_51950,
STRING_ENCODING_WINDOWS_57002,
STRING_ENCODING_WINDOWS_57003,
STRING_ENCODING_WINDOWS_57004,
STRING_ENCODING_WINDOWS_57005,
STRING_ENCODING_WINDOWS_57006,
STRING_ENCODING_WINDOWS_57007,
STRING_ENCODING_WINDOWS_57008,
STRING_ENCODING_WINDOWS_57009,
STRING_ENCODING_WINDOWS_57010,
STRING_ENCODING_WINDOWS_57011,
STRING_ENCODING_IBM_813,
STRING_ENCODING_IBM_943_P130_1999,
STRING_ENCODING_IBM_33722,
STRING_ENCODING_WINDOWS_949,
STRING_ENCODING_IBM_1363,
STRING_ENCODING_IBM_1386,
STRING_ENCODING_IBM_1373,
STRING_ENCODING_IBM_5471,
STRING_ENCODING_IBM_874,
// Add more encodings here.
// Sentinel value after the last explicitly specified encoding.
STRING_ENCODING_MAX_SPECIFIED,
/*
* The environment-specified "default" encoding for this process.
*/
STRING_ENCODING_DEFAULT = -1,
STRING_ENCODING_UNKNOWN = -2,
/*
* UTF-16 and UTF-32 in native byte order.
*/
STRING_ENCODING_UTF16 = STRING_ENCODING_UTF16_LE,
STRING_ENCODING_UTF32 = STRING_ENCODING_UTF32_LE,
} StringEncoding;
const char *Unicode_EncodingEnumToName(StringEncoding encoding);
StringEncoding Unicode_EncodingNameToEnum(const char *encodingName);
Bool Unicode_IsEncodingValid(StringEncoding encoding);
void Unicode_Init(int argc, char ***argv, char ***envp);
void Unicode_InitEx(int argc, char ***argv, char ***envp,
const char *icuDataDir);
#if defined (_WIN32)
void Unicode_InitW(int argc, utf16_t **wargv, utf16_t **wenvp,
char ***argv, char ***envp);
#endif
StringEncoding Unicode_GetCurrentEncoding(void);
StringEncoding Unicode_ResolveEncoding(StringEncoding encoding);
#ifdef __cplusplus
}
#endif
#endif // _UNICODE_TYPES_H_

View File

@@ -0,0 +1,694 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* util.h --
*
* misc util functions
*/
#ifndef UTIL_H
#define UTIL_H
#include <stdarg.h>
#include <string.h>
#ifndef VMKBOOT
#include <stdlib.h>
#endif
#ifdef _WIN32
#ifdef USERLEVEL
#include <tchar.h> /* Needed for MBCS string functions */
#include <windows.h> /* for definition of HANDLE */
#endif
#else
#include <sys/types.h>
#include "errno.h"
#endif
#include "vm_assert.h"
#include "vm_basic_defs.h"
#include "unicodeTypes.h"
/*
* Define the Util_ThreadID type, and assorted standard bits.
*/
#if defined(_WIN32)
typedef DWORD Util_ThreadID;
#else
#include <unistd.h>
#if defined(__APPLE__) || defined(__FreeBSD__)
#include <pthread.h>
typedef pthread_t Util_ThreadID;
#else // Linux et al
typedef pid_t Util_ThreadID;
#endif
#endif
uint32 CRC_Compute(const uint8 *buf, int len);
uint32 Util_Checksum32(const uint32 *buf, int len);
uint32 Util_Checksum(const uint8 *buf, int len);
uint32 Util_Checksumv(void *iov, int numEntries);
uint32 Util_HashString(const char *str);
Unicode Util_ExpandString(ConstUnicode fileName);
void Util_ExitThread(int);
NORETURN void Util_ExitProcessAbruptly(int);
int Util_HasAdminPriv(void);
#if defined _WIN32 && defined USERLEVEL
int Util_TokenHasAdminPriv(HANDLE token);
int Util_TokenHasInteractPriv(HANDLE token);
#endif
Bool Util_Data2Buffer(char *buf, size_t bufSize, const void *data0,
size_t dataSize);
char *Util_GetCanonicalPath(const char *path);
#ifdef _WIN32
char *Util_CompatGetCanonicalPath(const char *path);
char *Util_GetCanonicalPathForHash(const char *path);
char *Util_CompatGetLowerCaseCanonicalPath(const char* path);
#endif
int Util_BumpNoFds(uint32 *cur, uint32 *wanted);
Bool Util_CanonicalPathsIdentical(const char *path1, const char *path2);
Bool Util_IsAbsolutePath(const char *path);
unsigned Util_GetPrime(unsigned n0);
Util_ThreadID Util_GetCurrentThreadId(void);
char *Util_DeriveFileName(const char *source,
const char *name,
const char *ext);
char *Util_CombineStrings(char **sources, int count);
char **Util_SeparateStrings(char *source, int *count);
typedef struct UtilSingleUseResource UtilSingleUseResource;
UtilSingleUseResource *Util_SingleUseAcquire(const char *name);
void Util_SingleUseRelease(UtilSingleUseResource *res);
#ifndef _WIN32
Bool Util_IPv4AddrValid(const char *addr);
Bool Util_IPv6AddrValid(const char *addr);
Bool Util_IPAddrValid(const char *addr);
#endif
#if defined(__linux__) || defined(__FreeBSD__) || defined(sun)
Bool Util_GetProcessName(pid_t pid, char *bufOut, size_t bufOutSize);
#endif
#if defined __linux__ && !defined VMX86_SERVER
Bool Util_IsPhysicalSSD(const char* device);
#endif
// backtrace functions and utilities
#define UTIL_BACKTRACE_LINE_LEN (511)
typedef void (*Util_OutputFunc)(void *data, const char *fmt, ...);
void Util_Backtrace(int bugNr);
void Util_BacktraceFromPointer(uintptr_t *basePtr);
void Util_BacktraceFromPointerWithFunc(uintptr_t *basePtr,
Util_OutputFunc outFunc,
void *outFuncData);
void Util_BacktraceWithFunc(int bugNr,
Util_OutputFunc outFunc,
void *outFuncData);
void Util_BacktraceToBuffer(uintptr_t *basePtr,
uintptr_t *buffer, int len);
// sleep functions
void Util_Usleep(long usec);
void Util_Sleep(unsigned int sec);
int Util_CompareDotted(const char *s1, const char *s2);
/*
* This enum defines how Util_GetOpt should handle non-option arguments:
*
* UTIL_NONOPT_PERMUTE: Permute argv so that all non-options are at the end.
* UTIL_NONOPT_STOP: Stop when first non-option argument is seen.
* UTIL_NONOPT_ALL: Return each non-option argument as if it were
* an option with character code 1.
*/
typedef enum { UTIL_NONOPT_PERMUTE, UTIL_NONOPT_STOP, UTIL_NONOPT_ALL } Util_NonOptMode;
struct option;
int Util_GetOpt(int argc, char * const *argv, const struct option *opts,
Util_NonOptMode mode);
#if defined(VMX86_STATS)
Bool Util_QueryCStResidency(uint32 *numCpus, uint32 *numCStates,
uint64 **transitns, uint64 **residency,
uint64 **transTime, uint64 **residTime);
#endif
/*
* In util_shared.h
*/
#define UTIL_FASTRAND_SEED_MAX (0x7fffffff)
Bool Util_Throttle(uint32 count);
uint32 Util_FastRand(uint32 seed);
// Not thread safe!
void Util_OverrideHomeDir(const char *path);
/*
*-----------------------------------------------------------------------------
*
* Util_ValidateBytes --
*
* Check that memory is filled with the specified value.
*
* Results:
* NULL No error
* !NULL First address that doesn't have the proper value
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
static INLINE void *
Util_ValidateBytes(const void *ptr, // IN: ptr to check
size_t size, // IN: size of ptr
uint8 byteValue) // IN: memory must be filled with this
{
uint8 *p;
uint8 *end;
uint64 bigValue;
ASSERT(ptr);
if (size == 0) {
return NULL;
}
p = (uint8 *) ptr;
end = p + size;
/* Compare bytes until a "nice" boundary is achieved. */
while ((uintptr_t) p % sizeof bigValue) {
if (*p != byteValue) {
return p;
}
p++;
if (p == end) {
return NULL;
}
}
/* Compare using a "nice sized" chunk for a long as possible. */
memset(&bigValue, (int) byteValue, sizeof bigValue);
while (p + sizeof bigValue <= end) {
if (*((uint64 *) p) != bigValue) {
/* That's not right... let the loop below report the exact address. */
break;
}
size -= sizeof bigValue;
p += sizeof bigValue;
}
/* Handle any trailing bytes. */
while (p < end) {
if (*p != byteValue) {
return p;
}
p++;
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* Util_BufferIsEmpty --
*
* Determine if the specified buffer of 'len' bytes starting at 'base'
* is empty (i.e. full of zeroes).
*
* Results:
* TRUE Yes
* FALSE No
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
static INLINE Bool
Util_BufferIsEmpty(void const *base, // IN:
size_t len) // IN:
{
return Util_ValidateBytes(base, len, '\0') == NULL;
}
Bool Util_MakeSureDirExistsAndAccessible(char const *path,
unsigned int mode);
#if _WIN32
# define DIRSEPS "\\"
# define DIRSEPS_W L"\\"
# define DIRSEPC '\\'
# define DIRSEPC_W L'\\'
# define VALID_DIRSEPS "\\/"
# define VALID_DIRSEPS_W L"\\/"
# define CUR_DIRS_W L"."
# define CUR_DIRC_W L'.'
#else
# define DIRSEPS "/"
# define DIRSEPC '/'
# define VALID_DIRSEPS DIRSEPS
#endif
#define CURR_DIRS "."
#define CURR_DIRC '.'
/*
*-----------------------------------------------------------------------
*
* Util_Safe[Malloc, Realloc, Calloc, Strdup] and
* Util_Safe[Malloc, Realloc, Calloc, Strdup]Bug --
*
* These functions work just like the standard C library functions
* (except Util_SafeStrdup[,Bug]() accept NULL, see below),
* but will not fail. Instead they Panic(), printing the file and
* line number of the caller, if the underlying library function
* fails. The Util_SafeFnBug functions print bugNumber in the
* Panic() message.
*
* These functions should only be used when there is no way to
* gracefully recover from the error condition.
*
* The internal versions of these functions expect a bug number
* as the first argument. If that bug number is something other
* than -1, the panic message will include the bug number.
*
* Since Util_SafeStrdup[,Bug]() do not need to return NULL
* on error, they have been extended to accept the null pointer
* (and return it). The competing view is that they should
* panic on NULL. This is a convenience vs. strictness argument.
* Convenience wins. -- edward
*
* Results:
* The freshly allocated memory.
*
* Side effects:
* Panic() if the library function fails.
*
*--------------------------------------------------------------------------
*/
void *UtilSafeMalloc0(size_t size);
void *UtilSafeMalloc1(size_t size,
int bugNumber, const char *file, int lineno);
void *UtilSafeRealloc0(void *ptr, size_t size);
void *UtilSafeRealloc1(void *ptr, size_t size,
int bugNumber, const char *file, int lineno);
void *UtilSafeCalloc0(size_t nmemb, size_t size);
void *UtilSafeCalloc1(size_t nmemb, size_t size,
int bugNumber, const char *file, int lineno);
char *UtilSafeStrdup0(const char *s);
char *UtilSafeStrdup1(const char *s,
int bugNumber, const char *file, int lineno);
char *UtilSafeStrndup0(const char *s, size_t n);
char *UtilSafeStrndup1(const char *s, size_t n,
int bugNumber, const char *file, int lineno);
/*
* Debug builds carry extra arguments into the allocation functions for
* better error reporting. Non-debug builds don't pay this extra overhead.
*/
#ifdef VMX86_DEBUG
#define Util_SafeMalloc(_size) \
UtilSafeMalloc1((_size), -1, __FILE__, __LINE__)
#define Util_SafeMallocBug(_bugNr, _size) \
UtilSafeMalloc1((_size),(_bugNr), __FILE__, __LINE__)
#define Util_SafeRealloc(_ptr, _size) \
UtilSafeRealloc1((_ptr), (_size), -1, __FILE__, __LINE__)
#define Util_SafeReallocBug(_bugNr, _ptr, _size) \
UtilSafeRealloc1((_ptr), (_size), (_bugNr), __FILE__, __LINE__)
#define Util_SafeCalloc(_nmemb, _size) \
UtilSafeCalloc1((_nmemb), (_size), -1, __FILE__, __LINE__)
#define Util_SafeCallocBug(_bugNr, _nmemb, _size) \
UtilSafeCalloc1((_nmemb), (_size), (_bugNr), __FILE__, __LINE__)
#define Util_SafeStrndup(_str, _size) \
UtilSafeStrndup1((_str), (_size), -1, __FILE__, __LINE__)
#define Util_SafeStrndupBug(_bugNr, _str, _size) \
UtilSafeStrndup1((_str), (_size), (_bugNr), __FILE__, __LINE__)
#define Util_SafeStrdup(_str) \
UtilSafeStrdup1((_str), -1, __FILE__, __LINE__)
#define Util_SafeStrdupBug(_bugNr, _str) \
UtilSafeStrdup1((_str), (_bugNr), __FILE__, __LINE__)
#else /* VMX86_DEBUG */
#define Util_SafeMalloc(_size) \
UtilSafeMalloc0((_size))
#define Util_SafeMallocBug(_bugNr, _size) \
UtilSafeMalloc0((_size))
#define Util_SafeRealloc(_ptr, _size) \
UtilSafeRealloc0((_ptr), (_size))
#define Util_SafeReallocBug(_ptr, _size) \
UtilSafeRealloc0((_ptr), (_size))
#define Util_SafeCalloc(_nmemb, _size) \
UtilSafeCalloc0((_nmemb), (_size))
#define Util_SafeCallocBug(_bugNr, _nmemb, _size) \
UtilSafeCalloc0((_nmemb), (_size))
#define Util_SafeStrndup(_str, _size) \
UtilSafeStrndup0((_str), (_size))
#define Util_SafeStrndupBug(_bugNr, _str, _size) \
UtilSafeStrndup0((_str), (_size))
#define Util_SafeStrdup(_str) \
UtilSafeStrdup0((_str))
#define Util_SafeStrdupBug(_bugNr, _str) \
UtilSafeStrdup0((_str))
#endif /* VMX86_DEBUG */
void *Util_Memcpy(void *dest, const void *src, size_t count);
/*
*-----------------------------------------------------------------------------
*
* Util_Zero --
*
* Zeros out bufSize bytes of buf. NULL is legal.
*
* Results:
* None.
*
* Side effects:
* See above.
*
*-----------------------------------------------------------------------------
*/
static INLINE void
Util_Zero(void *buf, // OUT
size_t bufSize) // IN
{
if (buf != NULL) {
#if defined _WIN32 && defined USERLEVEL
/*
* Simple memset calls might be optimized out. See CERT advisory
* MSC06-C.
*/
SecureZeroMemory(buf, bufSize);
#else
memset(buf, 0, bufSize);
#if !defined _WIN32
/*
* Memset calls before free might be optimized out. See PR1248269.
*/
__asm__ __volatile__("" : : "r"(&buf) : "memory");
#endif
#endif
}
}
/*
*-----------------------------------------------------------------------------
*
* Util_ZeroString --
*
* Zeros out a NULL-terminated string. NULL is legal.
*
* Results:
* None.
*
* Side effects:
* See above.
*
*-----------------------------------------------------------------------------
*/
static INLINE void
Util_ZeroString(char *str) // IN/OUT
{
if (str != NULL) {
Util_Zero(str, strlen(str));
}
}
#ifndef VMKBOOT
/*
*-----------------------------------------------------------------------------
*
* Util_ZeroFree --
*
* Zeros out bufSize bytes of buf, and then frees it. NULL is
* legal.
*
* Results:
* None.
*
* Side effects:
* buf is zeroed, and then free() is called on it.
*
*-----------------------------------------------------------------------------
*/
static INLINE void
Util_ZeroFree(void *buf, // OUT
size_t bufSize) // IN
{
if (buf != NULL) {
Util_Zero(buf, bufSize);
free(buf);
}
}
/*
*-----------------------------------------------------------------------------
*
* Util_ZeroFreeString --
*
* Zeros out a NULL-terminated string, and then frees it. NULL is
* legal.
*
* Results:
* None.
*
* Side effects:
* str is zeroed, and then free() is called on it.
*
*-----------------------------------------------------------------------------
*/
static INLINE void
Util_ZeroFreeString(char *str) // IN
{
if (str != NULL) {
Util_ZeroString(str);
free(str);
}
}
#ifdef _WIN32
/*
*-----------------------------------------------------------------------------
*
* Util_ZeroFreeStringW --
*
* Zeros out a NUL-terminated wide-character string, and then frees it.
* NULL is legal.
*
* Results:
* None.
*
* Side effects:
* str is zeroed, and then free() is called on it.
*
*-----------------------------------------------------------------------------
*/
static INLINE void
Util_ZeroFreeStringW(wchar_t *str) // IN
{
if (str != NULL) {
Util_Zero(str, wcslen(str) * sizeof *str);
free(str);
}
}
#endif // _WIN32
/*
*-----------------------------------------------------------------------------
*
* Util_FreeList --
* Util_FreeStringList --
*
* Free a list (actually a vector) of allocated objects.
* The list (vector) itself is also freed.
*
* The list either has a specified length or is
* argv-style NULL terminated (if length is negative).
*
* The list can be NULL, in which case no operation is performed.
*
* Results:
* None
*
* Side effects:
* errno or Windows last error is preserved.
*
*-----------------------------------------------------------------------------
*/
static INLINE void
Util_FreeList(void **list, // IN/OUT: the list to free
ssize_t length) // IN: the length
{
if (list == NULL) {
ASSERT(length <= 0);
return;
}
if (length >= 0) {
ssize_t i;
for (i = 0; i < length; i++) {
free(list[i]);
DEBUG_ONLY(list[i] = NULL);
}
} else {
void **s;
for (s = list; *s != NULL; s++) {
free(*s);
DEBUG_ONLY(*s = NULL);
}
}
free(list);
}
static INLINE void
Util_FreeStringList(char **list, // IN/OUT: the list to free
ssize_t length) // IN: the length
{
Util_FreeList((void **) list, length);
}
#endif
#ifndef _WIN32
/*
*-----------------------------------------------------------------------------
*
* Util_IsFileDescriptorOpen --
*
* Check if given file descriptor is open.
*
* Results:
* TRUE if fd is open.
*
* Side effects:
* Clobbers errno.
*
*-----------------------------------------------------------------------------
*/
static INLINE Bool
Util_IsFileDescriptorOpen(int fd) // IN
{
return (lseek(fd, 0L, SEEK_CUR) == -1) ? errno != EBADF : TRUE;
}
#endif /* !_WIN32 */
/*
*-----------------------------------------------------------------------------
*
* Util_Memcpy32 --
*
* Special purpose version of memcpy that requires nbytes be a
* multiple of 4. This assumption lets us have a very small,
* inlineable implementation.
*
* Results:
* dst
*
* Side effects:
* See above.
*
*-----------------------------------------------------------------------------
*/
static INLINE void *
Util_Memcpy32(void *dst, const void *src, size_t nbytes)
{
ASSERT((nbytes % 4) == 0);
#if defined __GNUC__ && (defined(__i386__) || defined(__x86_64__))
do {
int dummy0, dummy1, dummy2;
__asm__ __volatile__(
"cld \n\t"
"rep ; movsl" "\n\t"
: "=&c" (dummy0), "=&D" (dummy1), "=&S" (dummy2)
: "0" (nbytes / 4), "1" ((long) dst), "2" ((long) src)
: "memory", "cc"
);
return dst;
} while (0);
#else
return memcpy(dst, src, nbytes);
#endif
}
#endif /* UTIL_H */

View File

@@ -0,0 +1,359 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* 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 REGENTS 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 REGENTS 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.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* vm_assert.h --
*
* The basic assertion facility for all VMware code.
*
* For proper use, see bora/doc/assert and
* http://vmweb.vmware.com/~mts/WebSite/guide/programming/asserts.html.
*/
#ifndef _VM_ASSERT_H_
#define _VM_ASSERT_H_
// XXX not necessary except some places include vm_assert.h improperly
#include "vm_basic_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Some bits of vmcore are used in VMKernel code and cannot have
* the VMKERNEL define due to other header dependencies.
*/
#if defined(VMKERNEL) && !defined(VMKPANIC)
#define VMKPANIC 1
#endif
/*
* Internal macros, functions, and strings
*
* The monitor wants to save space at call sites, so it has specialized
* functions for each situation. User level wants to save on implementation
* so it uses generic functions.
*/
#if !defined VMM || defined MONITOR_APP // {
#if defined VMKPANIC
#include "vmk_assert.h"
#else /* !VMKPANIC */
#define _ASSERT_PANIC(name) \
Panic(_##name##Fmt "\n", __FILE__, __LINE__)
#define _ASSERT_PANIC_BUG(bug, name) \
Panic(_##name##Fmt " bugNr=%d\n", __FILE__, __LINE__, bug)
#define _ASSERT_PANIC_NORETURN(name) \
Panic(_##name##Fmt "\n", __FILE__, __LINE__)
#define _ASSERT_PANIC_BUG_NORETURN(bug, name) \
Panic(_##name##Fmt " bugNr=%d\n", __FILE__, __LINE__, bug)
#endif /* VMKPANIC */
#endif // }
// These strings don't have newline so that a bug can be tacked on.
#define _AssertPanicFmt "PANIC %s:%d"
#define _AssertAssertFmt "ASSERT %s:%d"
#define _AssertVerifyFmt "VERIFY %s:%d"
#define _AssertNotImplementedFmt "NOT_IMPLEMENTED %s:%d"
#define _AssertNotReachedFmt "NOT_REACHED %s:%d"
#define _AssertMemAllocFmt "MEM_ALLOC %s:%d"
#define _AssertNotTestedFmt "NOT_TESTED %s:%d"
/*
* Panic and log functions
*/
void Log(const char *fmt, ...) PRINTF_DECL(1, 2);
void Warning(const char *fmt, ...) PRINTF_DECL(1, 2);
#if defined VMKPANIC
void Panic_SaveRegs(void);
#ifdef VMX86_DEBUG
void Panic_NoSave(const char *fmt, ...) PRINTF_DECL(1, 2);
#else
NORETURN void Panic_NoSave(const char *fmt, ...) PRINTF_DECL(1, 2);
#endif
NORETURN void Panic_NoSaveNoReturn(const char *fmt, ...) PRINTF_DECL(1, 2);
#define Panic(fmt...) do { \
Panic_SaveRegs(); \
Panic_NoSave(fmt); \
} while(0)
#define Panic_NoReturn(fmt...) do { \
Panic_SaveRegs(); \
Panic_NoSaveNoReturn(fmt); \
} while(0)
#else
NORETURN void Panic(const char *fmt, ...) PRINTF_DECL(1, 2);
#endif
void LogThrottled(uint32 *count, const char *fmt, ...) PRINTF_DECL(2, 3);
void WarningThrottled(uint32 *count, const char *fmt, ...) PRINTF_DECL(2, 3);
#ifndef ASSERT_IFNOT
/*
* PR 271512: When compiling with gcc, catch assignments inside an ASSERT.
*
* 'UNLIKELY' is defined with __builtin_expect, which does not warn when
* passed an assignment (gcc bug 36050). To get around this, we put 'cond'
* in an 'if' statement and make sure it never gets executed by putting
* that inside of 'if (0)'. We use gcc's statement expression syntax to
* make ASSERT an expression because some code uses it that way.
*
* Since statement expression syntax is a gcc extension and since it's
* not clear if this is a problem with other compilers, the ASSERT
* definition was not changed for them. Using a bare 'cond' with the
* ternary operator may provide a solution.
*/
#ifdef __GNUC__
#define ASSERT_IFNOT(cond, panic) \
({if (UNLIKELY(!(cond))) { panic; if (0) { if (cond) {;}}} (void)0;})
#else
#define ASSERT_IFNOT(cond, panic) \
(UNLIKELY(!(cond)) ? (panic) : (void)0)
#endif
#endif
/*
* Assert, panic, and log macros
*
* Some of these are redefined below undef !VMX86_DEBUG.
* ASSERT() is special cased because of interaction with Windows DDK.
*/
#if defined VMX86_DEBUG
#undef ASSERT
#define ASSERT(cond) ASSERT_IFNOT(cond, _ASSERT_PANIC(AssertAssert))
#define ASSERT_BUG(bug, cond) \
ASSERT_IFNOT(cond, _ASSERT_PANIC_BUG(bug, AssertAssert))
#endif
#undef VERIFY
#define VERIFY(cond) \
ASSERT_IFNOT(cond, _ASSERT_PANIC_NORETURN(AssertVerify))
#define VERIFY_BUG(bug, cond) \
ASSERT_IFNOT(cond, _ASSERT_PANIC_BUG_NORETURN(bug, AssertVerify))
#define PANIC() _ASSERT_PANIC(AssertPanic)
#define PANIC_BUG(bug) _ASSERT_PANIC_BUG(bug, AssertPanic)
#define ASSERT_NOT_IMPLEMENTED(cond) \
ASSERT_IFNOT(cond, NOT_IMPLEMENTED())
#define ASSERT_NOT_IMPLEMENTED_BUG(bug, cond) \
ASSERT_IFNOT(cond, NOT_IMPLEMENTED_BUG(bug))
#if defined VMKPANIC || defined VMM
#define NOT_IMPLEMENTED() _ASSERT_PANIC_NORETURN(AssertNotImplemented)
#else
#define NOT_IMPLEMENTED() _ASSERT_PANIC(AssertNotImplemented)
#endif
#if defined VMM
#define NOT_IMPLEMENTED_BUG(bug) \
_ASSERT_PANIC_BUG_NORETURN(bug, AssertNotImplemented)
#else
#define NOT_IMPLEMENTED_BUG(bug) _ASSERT_PANIC_BUG(bug, AssertNotImplemented)
#endif
#if defined VMKPANIC || defined VMM
#define NOT_REACHED() _ASSERT_PANIC_NORETURN(AssertNotReached)
#else
#define NOT_REACHED() _ASSERT_PANIC(AssertNotReached)
#endif
#define ASSERT_MEM_ALLOC(cond) \
ASSERT_IFNOT(cond, _ASSERT_PANIC(AssertMemAlloc))
#ifdef VMX86_DEVEL
#define ASSERT_DEVEL(cond) ASSERT(cond)
#define NOT_TESTED() Warning(_AssertNotTestedFmt "\n", __FILE__, __LINE__)
#else
#define ASSERT_DEVEL(cond) ((void)0)
#define NOT_TESTED() Log(_AssertNotTestedFmt "\n", __FILE__, __LINE__)
#endif
#define ASSERT_NO_INTERRUPTS() ASSERT(!INTERRUPTS_ENABLED())
#define ASSERT_HAS_INTERRUPTS() ASSERT(INTERRUPTS_ENABLED())
#define ASSERT_NOT_TESTED(cond) (UNLIKELY(!(cond)) ? NOT_TESTED() : (void)0)
#define NOT_TESTED_ONCE() DO_ONCE(NOT_TESTED())
#define NOT_TESTED_1024() \
do { \
static uint16 count = 0; \
if (UNLIKELY(count == 0)) { NOT_TESTED(); } \
count = (count + 1) & 1023; \
} while (0)
#define LOG_ONCE(_s) DO_ONCE(Log _s)
/*
* Redefine macros that are only in debug versions
*/
#if !defined VMX86_DEBUG // {
#undef ASSERT
#define ASSERT(cond) ((void)0)
#define ASSERT_BUG(bug, cond) ((void)0)
/*
* Expand NOT_REACHED() as appropriate for each situation.
*
* Mainly, we want the compiler to infer the same control-flow
* information as it would from Panic(). Otherwise, different
* compilation options will lead to different control-flow-derived
* errors, causing some make targets to fail while others succeed.
*
* VC++ has the __assume() built-in function which we don't trust
* (see bug 43485); gcc has no such construct; we just panic in
* userlevel code. The monitor doesn't want to pay the size penalty
* (measured at 212 bytes for the release vmm for a minimal infinite
* loop; panic would cost even more) so it does without and lives
* with the inconsistency.
*/
#if defined VMKPANIC || defined VMM
#undef NOT_REACHED
#if defined __GNUC__ && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 5)
#define NOT_REACHED() (__builtin_unreachable())
#else
#define NOT_REACHED() ((void)0)
#endif
#else
// keep debug definition
#endif
#undef LOG_UNEXPECTED
#define LOG_UNEXPECTED(bug) ((void)0)
#undef ASSERT_NOT_TESTED
#define ASSERT_NOT_TESTED(cond) ((void)0)
#undef NOT_TESTED
#define NOT_TESTED() ((void)0)
#undef NOT_TESTED_ONCE
#define NOT_TESTED_ONCE() ((void)0)
#undef NOT_TESTED_1024
#define NOT_TESTED_1024() ((void)0)
#endif // !VMX86_DEBUG }
/*
* Compile-time assertions.
*
* ASSERT_ON_COMPILE does not use the common
* switch (0) { case 0: case (e): ; } trick because some compilers (e.g. MSVC)
* generate code for it.
*
* The implementation uses both enum and typedef because the typedef alone is
* insufficient; gcc allows arrays to be declared with non-constant expressions
* (even in typedefs, where it makes no sense).
*
* NOTE: if GCC ever changes so that it ignores unused types altogether, this
* assert might not fire! We explicitly mark it as unused because GCC 4.8+
* uses -Wunused-local-typedefs as part of -Wall, which means the typedef will
* generate a warning.
*/
#define ASSERT_ON_COMPILE(e) \
do { \
enum { AssertOnCompileMisused = ((e) ? 1 : -1) }; \
UNUSED_TYPE(typedef char AssertOnCompileFailed[AssertOnCompileMisused]); \
} while (0)
/*
* To put an ASSERT_ON_COMPILE() outside a function, wrap it
* in MY_ASSERTS(). The first parameter must be unique in
* each .c file where it appears. For example,
*
* MY_ASSERTS(FS3_INT,
* ASSERT_ON_COMPILE(sizeof(FS3_DiskLock) == 128);
* ASSERT_ON_COMPILE(sizeof(FS3_DiskLockReserved) == DISK_BLOCK_SIZE);
* ASSERT_ON_COMPILE(sizeof(FS3_DiskBlock) == DISK_BLOCK_SIZE);
* ASSERT_ON_COMPILE(sizeof(Hardware_DMIUUID) == 16);
* )
*
* Caution: ASSERT() within MY_ASSERTS() is silently ignored.
* The same goes for anything else not evaluated at compile time.
*/
#define MY_ASSERTS(name, assertions) \
static INLINE void name(void) { \
assertions \
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* ifndef _VM_ASSERT_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,553 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* vm_basic_asm_x86.h
*
* Basic IA32 asm macros
*/
#ifndef _VM_BASIC_ASM_X86_H_
#define _VM_BASIC_ASM_X86_H_
#ifdef VM_X86_64
/*
* The gcc inline asm uses the "A" constraint which differs in 32 & 64
* bit mode. 32 bit means eax and edx, 64 means rax or rdx.
*/
#error "x86-64 not supported"
#endif
/*
* XTEST
* Return TRUE if processor is in transaction region.
*
*/
#if defined(__GNUC__) && (defined(VMM) || defined(VMKERNEL) || defined(FROBOS))
static INLINE Bool
xtest(void)
{
uint8 al;
__asm__ __volatile__(".byte 0x0f, 0x01, 0xd6 # xtest \n"
"setnz %%al\n"
: "=a"(al) : : "cc");
return al;
}
#endif /* __GNUC__ */
/*
* FXSAVE/FXRSTOR
* save/restore SIMD/MMX fpu state
*
* The pointer passed in must be 16-byte aligned.
*
* Intel and AMD processors behave differently w.r.t. fxsave/fxrstor. Intel
* processors unconditionally save the exception pointer state (instruction
* ptr., data ptr., and error instruction opcode). FXSAVE_ES1 and FXRSTOR_ES1
* work correctly for Intel processors.
*
* AMD processors only save the exception pointer state if ES=1. This leads to a
* security hole whereby one process/VM can inspect the state of another process
* VM. The AMD recommended workaround involves clobbering the exception pointer
* state unconditionally, and this is implemented in FXRSTOR_AMD_ES0. Note that
* FXSAVE_ES1 will only save the exception pointer state for AMD processors if
* ES=1.
*
* The workaround (FXRSTOR_AMD_ES0) only costs 1 cycle more than just doing an
* fxrstor, on both AMD Opteron and Intel Core CPUs.
*/
#if defined(__GNUC__)
static INLINE void
FXSAVE_ES1(void *save)
{
__asm__ __volatile__ ("fxsave %0\n" : "=m" (*(uint8 *)save) : : "memory");
}
static INLINE void
FXRSTOR_ES1(const void *load)
{
__asm__ __volatile__ ("fxrstor %0\n"
: : "m" (*(const uint8 *)load) : "memory");
}
static INLINE void
FXRSTOR_AMD_ES0(const void *load)
{
uint64 dummy = 0;
__asm__ __volatile__
("fnstsw %%ax \n" // Grab x87 ES bit
"bt $7,%%ax \n" // Test ES bit
"jnc 1f \n" // Jump if ES=0
"fnclex \n" // ES=1. Clear it so fild doesn't trap
"1: \n"
"ffree %%st(7) \n" // Clear tag bit - avoid poss. stack overflow
"fildl %0 \n" // Dummy Load from "safe address" changes all
// x87 exception pointers.
"fxrstor %1 \n"
:
: "m" (dummy), "m" (*(const uint8 *)load)
: "ax", "memory");
}
#endif /* __GNUC__ */
/*
* XSAVE/XRSTOR
* save/restore GSSE/SIMD/MMX fpu state
*
* The pointer passed in must be 64-byte aligned.
* See above comment for more information.
*/
#if defined(__GNUC__) && (defined(VMM) || defined(VMKERNEL) || defined(FROBOS))
static INLINE void
XSAVE_ES1(void *save, uint64 mask)
{
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
__asm__ __volatile__ (
".byte 0x0f, 0xae, 0x21 \n"
:
: "c" ((uint8 *)save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#else
__asm__ __volatile__ (
"xsave %0 \n"
: "=m" (*(uint8 *)save)
: "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#endif
}
static INLINE void
XSAVEOPT_ES1(void *save, uint64 mask)
{
__asm__ __volatile__ (
".byte 0x0f, 0xae, 0x31 \n"
:
: "c" ((uint8 *)save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
}
static INLINE void
XRSTOR_ES1(const void *load, uint64 mask)
{
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
__asm__ __volatile__ (
".byte 0x0f, 0xae, 0x29 \n"
:
: "c" ((const uint8 *)load),
"a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#else
__asm__ __volatile__ (
"xrstor %0 \n"
:
: "m" (*(const uint8 *)load),
"a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#endif
}
static INLINE void
XRSTOR_AMD_ES0(const void *load, uint64 mask)
{
uint64 dummy = 0;
__asm__ __volatile__
("fnstsw %%ax \n" // Grab x87 ES bit
"bt $7,%%ax \n" // Test ES bit
"jnc 1f \n" // Jump if ES=0
"fnclex \n" // ES=1. Clear it so fild doesn't trap
"1: \n"
"ffree %%st(7) \n" // Clear tag bit - avoid poss. stack overflow
"fildl %0 \n" // Dummy Load from "safe address" changes all
// x87 exception pointers.
"mov %%ebx, %%eax \n"
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
".byte 0x0f, 0xae, 0x29 \n"
:
: "m" (dummy), "c" ((const uint8 *)load),
"b" ((uint32)mask), "d" ((uint32)(mask >> 32))
#else
"xrstor %1 \n"
:
: "m" (dummy), "m" (*(const uint8 *)load),
"b" ((uint32)mask), "d" ((uint32)(mask >> 32))
#endif
: "eax", "memory");
}
#endif /* __GNUC__ */
/*
*-----------------------------------------------------------------------------
*
* Div643232 --
*
* Unsigned integer division:
* The dividend is 64-bit wide
* The divisor is 32-bit wide
* The quotient is 32-bit wide
*
* Use this function if you are certain that:
* o Either the quotient will fit in 32 bits,
* o Or your code is ready to handle a #DE exception indicating overflow.
* If that is not the case, then use Div643264().
*
* Results:
* Quotient and remainder
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__)
static INLINE void
Div643232(uint64 dividend, // IN
uint32 divisor, // IN
uint32 *quotient, // OUT
uint32 *remainder) // OUT
{
__asm__(
"divl %4"
: "=a" (*quotient),
"=d" (*remainder)
: "0" ((uint32)dividend),
"1" ((uint32)(dividend >> 32)),
"rm" (divisor)
: "cc"
);
}
#elif defined _MSC_VER
static INLINE void
Div643232(uint64 dividend, // IN
uint32 divisor, // IN
uint32 *quotient, // OUT
uint32 *remainder) // OUT
{
__asm {
mov eax, DWORD PTR [dividend]
mov edx, DWORD PTR [dividend+4]
div DWORD PTR [divisor]
mov edi, DWORD PTR [quotient]
mov [edi], eax
mov edi, DWORD PTR [remainder]
mov [edi], edx
}
}
#else
#error No compiler defined for Div643232
#endif
#if defined(__GNUC__)
/*
*-----------------------------------------------------------------------------
*
* Div643264 --
*
* Unsigned integer division:
* The dividend is 64-bit wide
* The divisor is 32-bit wide
* The quotient is 64-bit wide
*
* Results:
* Quotient and remainder
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static INLINE void
Div643264(uint64 dividend, // IN
uint32 divisor, // IN
uint64 *quotient, // OUT
uint32 *remainder) // OUT
{
uint32 hQuotient;
uint32 lQuotient;
__asm__(
"divl %5" "\n\t"
"movl %%eax, %0" "\n\t"
"movl %4, %%eax" "\n\t"
"divl %5"
: "=&rm" (hQuotient),
"=a" (lQuotient),
"=d" (*remainder)
: "1" ((uint32)(dividend >> 32)),
"g" ((uint32)dividend),
"rm" (divisor),
"2" (0)
: "cc"
);
*quotient = (uint64)hQuotient << 32 | lQuotient;
}
#endif
/*
*-----------------------------------------------------------------------------
*
* Mul64x3264 --
*
* Unsigned integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Unsigned 64-bit integer multiplicand.
* Unsigned 32-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Unsigned 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) && \
!defined(MUL64_NO_ASM)
static INLINE uint64
Mul64x3264(uint64 multiplicand, uint32 multiplier, uint32 shift)
{
uint64 result;
uint32 tmp1, tmp2;
// ASSERT(shift >= 0 && shift < 64);
__asm__("mov %%eax, %2\n\t" // Save lo(multiplicand)
"mov %%edx, %%eax\n\t" // Get hi(multiplicand)
"mull %4\n\t" // p2 = hi(multiplicand) * multiplier
"xchg %%eax, %2\n\t" // Save lo(p2), get lo(multiplicand)
"mov %%edx, %1\n\t" // Save hi(p2)
"mull %4\n\t" // p1 = lo(multiplicand) * multiplier
"addl %2, %%edx\n\t" // hi(p1) += lo(p2)
"adcl $0, %1\n\t" // hi(p2) += carry from previous step
"cmpl $32, %%ecx\n\t" // shift < 32?
"jl 2f\n\t" // Go if so
"shll $1, %%eax\n\t" // Save lo(p1) bit 31 in CF in case shift=32
"mov %%edx, %%eax\n\t" // result = hi(p2):hi(p1) >> (shift & 31)
"mov %1, %%edx\n\t"
"shrdl %%edx, %%eax\n\t"
"mov $0, %2\n\t"
"adcl $0, %2\n\t" // Get highest order bit shifted out, from CF
"shrl %%cl, %%edx\n\t"
"jmp 3f\n"
"2:\n\t"
"xor %2, %2\n\t"
"shrdl %%edx, %%eax\n\t" // result = hi(p2):hi(p1):lo(p1) >> shift
"adcl $0, %2\n\t" // Get highest order bit shifted out, from CF
"shrdl %1, %%edx\n"
"3:\n\t"
"addl %2, %%eax\n\t" // result += highest order bit shifted out
"adcl $0, %%edx"
: "=A" (result), "=&r" (tmp1), "=&r" (tmp2)
: "0" (multiplicand), "rm" (multiplier), "c" (shift)
: "cc");
return result;
}
#elif defined _MSC_VER
#pragma warning(disable: 4035)
static INLINE uint64
Mul64x3264(uint64 multiplicand, uint32 multiplier, uint32 shift)
{
// ASSERT(shift >= 0 && shift < 64);
__asm {
mov eax, DWORD PTR [multiplicand+4] // Get hi(multiplicand)
mul DWORD PTR [multiplier] // p2 = hi(multiplicand) * multiplier
mov ecx, eax // Save lo(p2)
mov ebx, edx // Save hi(p2)
mov eax, DWORD PTR [multiplicand] // Get lo(multiplicand)
mul DWORD PTR [multiplier+0] // p1 = lo(multiplicand) * multiplier
add edx, ecx // hi(p1) += lo(p2)
adc ebx, 0 // hi(p2) += carry from previous step
mov ecx, DWORD PTR [shift] // Get shift
cmp ecx, 32 // shift < 32?
jl SHORT l2 // Go if so
shl eax, 1 // Save lo(p1) bit 31 in CF in case shift=32
mov eax, edx // result = hi(p2):hi(p1) >> (shift & 31)
mov edx, ebx
shrd eax, edx, cl
mov esi, 0
adc esi, 0 // Get highest order bit shifted out, from CF
shr edx, cl
jmp SHORT l3
l2:
xor esi, esi
shrd eax, edx, cl // result = hi(p2):hi(p1):lo(p1) >> shift
adc esi, 0 // Get highest order bit shifted out, from CF
shrd edx, ebx, cl
l3:
add eax, esi // result += highest order bit shifted out
adc edx, 0
}
// return with result in edx:eax
}
#pragma warning(default: 4035)
#else
#define MUL64_NO_ASM 1
#include "mul64.h"
#endif
/*
*-----------------------------------------------------------------------------
*
* Muls64x32s64 --
*
* Signed integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Signed 64-bit integer multiplicand.
* Unsigned 32-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Signed 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) && \
!defined(MUL64_NO_ASM)
static INLINE int64
Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
{
int64 result;
uint32 tmp1, tmp2;
// ASSERT(shift >= 0 && shift < 64);
__asm__("mov %%eax, %2\n\t" // Save lo(multiplicand)
"mov %%edx, %%eax\n\t" // Get hi(multiplicand)
"test %%eax, %%eax\n\t" // Check sign of multiplicand
"jl 0f\n\t" // Go if negative
"mull %4\n\t" // p2 = hi(multiplicand) * multiplier
"jmp 1f\n"
"0:\n\t"
"mull %4\n\t" // p2 = hi(multiplicand) * multiplier
"sub %4, %%edx\n" // hi(p2) += -1 * multiplier
"1:\n\t"
"xchg %%eax, %2\n\t" // Save lo(p2), get lo(multiplicand)
"mov %%edx, %1\n\t" // Save hi(p2)
"mull %4\n\t" // p1 = lo(multiplicand) * multiplier
"addl %2, %%edx\n\t" // hi(p1) += lo(p2)
"adcl $0, %1\n\t" // hi(p2) += carry from previous step
"cmpl $32, %%ecx\n\t" // shift < 32?
"jl 2f\n\t" // Go if so
"shll $1, %%eax\n\t" // Save lo(p1) bit 31 in CF in case shift=32
"mov %%edx, %%eax\n\t" // result = hi(p2):hi(p1) >> (shift & 31)
"mov %1, %%edx\n\t"
"shrdl %%edx, %%eax\n\t"
"mov $0, %2\n\t"
"adcl $0, %2\n\t" // Get highest order bit shifted out from CF
"sarl %%cl, %%edx\n\t"
"jmp 3f\n"
"2:\n\t"
"xor %2, %2\n\t"
"shrdl %%edx, %%eax\n\t" // result = hi(p2):hi(p1):lo(p1) >> shift
"adcl $0, %2\n\t" // Get highest order bit shifted out from CF
"shrdl %1, %%edx\n"
"3:\n\t"
"addl %2, %%eax\n\t" // result += highest order bit shifted out
"adcl $0, %%edx"
: "=A" (result), "=&r" (tmp1), "=&rm" (tmp2)
: "0" (multiplicand), "rm" (multiplier), "c" (shift)
: "cc");
return result;
}
#elif defined(_MSC_VER)
#pragma warning(disable: 4035)
static INLINE int64
Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
{
//ASSERT(shift >= 0 && shift < 64);
__asm {
mov eax, DWORD PTR [multiplicand+4] // Get hi(multiplicand)
test eax, eax // Check sign of multiplicand
jl SHORT l0 // Go if negative
mul DWORD PTR [multiplier] // p2 = hi(multiplicand) * multiplier
jmp SHORT l1
l0:
mul DWORD PTR [multiplier] // p2 = hi(multiplicand) * multiplier
sub edx, DWORD PTR [multiplier] // hi(p2) += -1 * multiplier
l1:
mov ecx, eax // Save lo(p2)
mov ebx, edx // Save hi(p2)
mov eax, DWORD PTR [multiplicand] // Get lo(multiplicand)
mul DWORD PTR [multiplier] // p1 = lo(multiplicand) * multiplier
add edx, ecx // hi(p1) += lo(p2)
adc ebx, 0 // hi(p2) += carry from previous step
mov ecx, DWORD PTR [shift] // Get shift
cmp ecx, 32 // shift < 32?
jl SHORT l2 // Go if so
shl eax, 1 // Save lo(p1) bit 31 in CF in case shift=32
mov eax, edx // result = hi(p2):hi(p1) >> (shift & 31)
mov edx, ebx
shrd eax, edx, cl
mov esi, 0
adc esi, 0 // Get highest order bit shifted out, from CF
sar edx, cl
jmp SHORT l3
l2:
xor esi, esi
shrd eax, edx, cl // result = hi(p2):hi(p1):lo(p1) << shift
adc esi, 0 // Get highest order bit shifted out, from CF
shrd edx, ebx, cl
l3:
add eax, esi // result += highest order bit shifted out
adc edx, 0
}
// return with result in edx:eax
}
#pragma warning(default: 4035)
#endif
#endif

View File

@@ -0,0 +1,616 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* vm_basic_asm_x86_64.h
*
* Basic x86_64 asm macros.
*/
#ifndef _VM_BASIC_ASM_X86_64_H_
#define _VM_BASIC_ASM_X86_64_H_
#ifndef VM_X86_64
#error "This file is x86-64 only!"
#endif
#if defined(_MSC_VER) && !defined(BORA_NO_WIN32_INTRINS)
#ifdef __cplusplus
extern "C" {
#endif
uint64 _umul128(uint64 multiplier, uint64 multiplicand,
uint64 *highProduct);
int64 _mul128(int64 multiplier, int64 multiplicand,
int64 *highProduct);
uint64 __shiftright128(uint64 lowPart, uint64 highPart, uint8 shift);
#ifdef __cplusplus
}
#endif
#pragma intrinsic(_umul128, _mul128, __shiftright128)
#endif // _MSC_VER
#if defined(__GNUC__)
/*
* GET_CURRENT_RIP
*
* Returns the current instruction pointer. In the example below:
*
* foo.c
* L123: Foo(GET_CURRENT_RIP())
*
* the return value from GET_CURRENT_RIP will point a debugger to L123.
*/
#define GET_CURRENT_RIP() ({ \
void *__rip; \
asm("lea 0(%%rip), %0;\n\t" \
: "=r" (__rip)); \
__rip; \
})
/*
* GET_CURRENT_LOCATION
*
* Updates the arguments with the values of the %rip, %rbp, and %rsp
* registers at the current code location where the macro is invoked.
*/
#define GET_CURRENT_LOCATION(rip, rbp, rsp) \
asm("lea 0(%%rip), %0\n" \
"mov %%rbp, %1\n" \
"mov %%rsp, %2\n" \
: "=r" (rip), "=r" (rbp), "=r" (rsp))
#endif
/*
* FXSAVE/FXRSTOR
* save/restore SIMD/MMX fpu state
*
* The pointer passed in must be 16-byte aligned.
*
* Intel and AMD processors behave differently w.r.t. fxsave/fxrstor. Intel
* processors unconditionally save the exception pointer state (instruction
* ptr., data ptr., and error instruction opcode). FXSAVE_ES1 and FXRSTOR_ES1
* work correctly for Intel processors.
*
* AMD processors only save the exception pointer state if ES=1. This leads to a
* security hole whereby one process/VM can inspect the state of another process
* VM. The AMD recommended workaround involves clobbering the exception pointer
* state unconditionally, and this is implemented in FXRSTOR_AMD_ES0. Note that
* FXSAVE_ES1 will only save the exception pointer state for AMD processors if
* ES=1.
*
* The workaround (FXRSTOR_AMD_ES0) only costs 1 cycle more than just doing an
* fxrstor, on both AMD Opteron and Intel Core CPUs.
*/
#if defined(__GNUC__)
static INLINE void
FXSAVE_ES1(void *save)
{
__asm__ __volatile__ ("fxsaveq %0 \n" : "=m" (*(uint8 *)save) : : "memory");
}
static INLINE void
FXSAVE_COMPAT_ES1(void *save)
{
__asm__ __volatile__ ("fxsave %0 \n" : "=m" (*(uint8 *)save) : : "memory");
}
static INLINE void
FXRSTOR_ES1(const void *load)
{
__asm__ __volatile__ ("fxrstorq %0 \n"
: : "m" (*(const uint8 *)load) : "memory");
}
static INLINE void
FXRSTOR_COMPAT_ES1(const void *load)
{
__asm__ __volatile__ ("fxrstor %0 \n"
: : "m" (*(const uint8 *)load) : "memory");
}
static INLINE void
FXRSTOR_AMD_ES0(const void *load)
{
uint64 dummy = 0;
__asm__ __volatile__
("fnstsw %%ax \n" // Grab x87 ES bit
"bt $7,%%ax \n" // Test ES bit
"jnc 1f \n" // Jump if ES=0
"fnclex \n" // ES=1. Clear it so fild doesn't trap
"1: \n"
"ffree %%st(7) \n" // Clear tag bit - avoid poss. stack overflow
"fildl %0 \n" // Dummy Load from "safe address" changes all
// x87 exception pointers.
"fxrstorq %1 \n"
:
: "m" (dummy), "m" (*(const uint8 *)load)
: "ax", "memory");
}
#endif /* __GNUC__ */
/*
* XSAVE/XRSTOR
* save/restore GSSE/SIMD/MMX fpu state
*
* The pointer passed in must be 64-byte aligned.
* See above comment for more information.
*/
#if defined(__GNUC__) && (defined(VMM) || defined(VMKERNEL) || defined(FROBOS))
static INLINE void
XSAVE_ES1(void *save, uint64 mask)
{
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
__asm__ __volatile__ (
".byte 0x48, 0x0f, 0xae, 0x21 \n"
:
: "c" ((uint8 *)save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#else
__asm__ __volatile__ (
"xsaveq %0 \n"
: "=m" (*(uint8 *)save)
: "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#endif
}
static INLINE void
XSAVE_COMPAT_ES1(void *save, uint64 mask)
{
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
__asm__ __volatile__ (
".byte 0x0f, 0xae, 0x21 \n"
:
: "c" ((uint8 *)save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#else
__asm__ __volatile__ (
"xsave %0 \n"
: "=m" (*(uint8 *)save)
: "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#endif
}
static INLINE void
XSAVEOPT_ES1(void *save, uint64 mask)
{
__asm__ __volatile__ (
".byte 0x48, 0x0f, 0xae, 0x31 \n"
:
: "c" ((uint8 *)save), "a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
}
static INLINE void
XRSTOR_ES1(const void *load, uint64 mask)
{
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
__asm__ __volatile__ (
".byte 0x48, 0x0f, 0xae, 0x29 \n"
:
: "c" ((const uint8 *)load),
"a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#else
__asm__ __volatile__ (
"xrstorq %0 \n"
:
: "m" (*(const uint8 *)load),
"a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#endif
}
static INLINE void
XRSTOR_COMPAT_ES1(const void *load, uint64 mask)
{
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
__asm__ __volatile__ (
".byte 0x0f, 0xae, 0x29 \n"
:
: "c" ((const uint8 *)load),
"a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#else
__asm__ __volatile__ (
"xrstor %0 \n"
:
: "m" (*(const uint8 *)load),
"a" ((uint32)mask), "d" ((uint32)(mask >> 32))
: "memory");
#endif
}
static INLINE void
XRSTOR_AMD_ES0(const void *load, uint64 mask)
{
uint64 dummy = 0;
__asm__ __volatile__
("fnstsw %%ax \n" // Grab x87 ES bit
"bt $7,%%ax \n" // Test ES bit
"jnc 1f \n" // Jump if ES=0
"fnclex \n" // ES=1. Clear it so fild doesn't trap
"1: \n"
"ffree %%st(7) \n" // Clear tag bit - avoid poss. stack overflow
"fildl %0 \n" // Dummy Load from "safe address" changes all
// x87 exception pointers.
"mov %%ebx, %%eax \n"
#if __GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ == 1
".byte 0x48, 0x0f, 0xae, 0x29 \n"
:
: "m" (dummy), "c" ((const uint8 *)load),
"b" ((uint32)mask), "d" ((uint32)(mask >> 32))
#else
"xrstorq %1 \n"
:
: "m" (dummy), "m" (*(const uint8 *)load),
"b" ((uint32)mask), "d" ((uint32)(mask >> 32))
#endif
: "eax", "memory");
}
#endif /* __GNUC__ */
/*
* XTEST
* Return TRUE if processor is in transaction region.
*
*/
#if defined(__GNUC__) && (defined(VMM) || defined(VMKERNEL) || defined(FROBOS))
static INLINE Bool
xtest(void)
{
uint8 al;
__asm__ __volatile__(".byte 0x0f, 0x01, 0xd6 # xtest \n"
"setnz %%al\n"
: "=a"(al) : : "cc");
return al;
}
#endif /* __GNUC__ */
/*
*-----------------------------------------------------------------------------
*
* Mul64x6464 --
*
* Unsigned integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Unsigned 64-bit integer multiplicand.
* Unsigned 64-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Unsigned 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__) && !defined(MUL64_NO_ASM)
static INLINE uint64
Mul64x6464(uint64 multiplicand,
uint64 multiplier,
uint32 shift)
{
/*
* Implementation:
* Multiply 64x64 bits to yield a full 128-bit product.
* Clear the carry bit (needed for the shift == 0 case).
* Shift result in RDX:RAX right by "shift".
* Add the carry bit. (If shift > 0, this is the highest order bit
* that was discarded by the shift; else it is 0.)
* Return the low-order 64 bits of the above.
*
*/
uint64 result, dummy;
__asm__("mulq %3 \n\t"
"clc \n\t"
"shrdq %b4, %1, %0 \n\t"
"adc $0, %0 \n\t"
: "=a" (result),
"=d" (dummy)
: "0" (multiplier),
"rm" (multiplicand),
"c" (shift)
: "cc");
return result;
}
#elif defined(_MSC_VER) && !defined(MUL64_NO_ASM)
static INLINE uint64
Mul64x6464(uint64 multiplicand,
uint64 multiplier,
uint32 shift)
{
/*
* Unfortunately, MSVC intrinsics don't give us access to the carry
* flag after a 128-bit shift, so the implementation is more
* awkward:
* Multiply 64x64 bits to yield a full 128-bit product.
* Shift result right by "shift".
* If shift != 0, extract and add in highest order bit that was
* discarded by the shift.
* Return the low-order 64 bits of the above.
*/
uint64 tmplo, tmphi;
tmplo = _umul128(multiplicand, multiplier, &tmphi);
if (shift == 0) {
return tmplo;
} else {
return __shiftright128(tmplo, tmphi, (uint8) shift) +
((tmplo >> (shift - 1)) & 1);
}
}
#else
#define MUL64_NO_ASM 1
#include "mul64.h"
#endif
/*
*-----------------------------------------------------------------------------
*
* Muls64x64s64 --
*
* Signed integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Signed 64-bit integer multiplicand.
* Unsigned 64-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Signed 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__) && !defined(MUL64_NO_ASM)
static inline int64
Muls64x64s64(int64 multiplicand,
int64 multiplier,
uint32 shift)
{
int64 result, dummy;
/* Implementation:
* Multiply 64x64 bits to yield a full 128-bit product.
* Clear the carry bit (needed for the shift == 0 case).
* Shift result in RDX:RAX right by "shift".
* Add the carry bit. (If shift > 0, this is the highest order bit
* that was discarded by the shift; else it is 0.)
* Return the low-order 64 bits of the above.
*
* Note: using the unsigned shrd instruction is correct because
* shift < 64 and we return only the low 64 bits of the shifted
* result.
*/
__asm__("imulq %3 \n\t"
"clc \n\t"
"shrdq %b4, %1, %0 \n\t"
"adc $0, %0 \n\t"
: "=a" (result),
"=d" (dummy)
: "0" (multiplier),
"rm" (multiplicand),
"c" (shift)
: "cc");
return result;
}
#elif defined(_MSC_VER) && !defined(MUL64_NO_ASM)
static INLINE int64
Muls64x64s64(int64 multiplicand,
int64 multiplier,
uint32 shift)
{
/*
* Unfortunately, MSVC intrinsics don't give us access to the carry
* flag after a 128-bit shift, so the implementation is more
* awkward:
* Multiply 64x64 bits to yield a full 128-bit product.
* Shift result right by "shift".
* If shift != 0, extract and add in highest order bit that was
* discarded by the shift.
* Return the low-order 64 bits of the above.
*
* Note: using an unsigned shift is correct because shift < 64 and
* we return only the low 64 bits of the shifted result.
*/
int64 tmplo, tmphi;
tmplo = _mul128(multiplicand, multiplier, &tmphi);
if (shift == 0) {
return tmplo;
} else {
return __shiftright128(tmplo, tmphi, (uint8) shift) +
((tmplo >> (shift - 1)) & 1);
}
}
#endif
#ifndef MUL64_NO_ASM
/*
*-----------------------------------------------------------------------------
*
* Mul64x3264 --
*
* Unsigned integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Unsigned 64-bit integer multiplicand.
* Unsigned 32-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Unsigned 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
static INLINE uint64
Mul64x3264(uint64 multiplicand, uint32 multiplier, uint32 shift)
{
return Mul64x6464(multiplicand, multiplier, shift);
}
/*
*-----------------------------------------------------------------------------
*
* Muls64x32s64 --
*
* Signed integer by fixed point multiplication, with rounding:
* result = floor(multiplicand * multiplier * 2**(-shift) + 0.5)
*
* Signed 64-bit integer multiplicand.
* Unsigned 32-bit fixed point multiplier, represented as
* (multiplier, shift), where shift < 64.
*
* Result:
* Signed 64-bit integer product.
*
*-----------------------------------------------------------------------------
*/
static INLINE int64
Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
{
return Muls64x64s64(multiplicand, multiplier, shift);
}
#endif
#if defined(__GNUC__)
static INLINE void *
uint64set(void *dst, uint64 val, uint64 count)
{
int dummy0;
int dummy1;
__asm__ __volatile__("\t"
"cld" "\n\t"
"rep ; stosq" "\n"
: "=c" (dummy0), "=D" (dummy1)
: "0" (count), "1" (dst), "a" (val)
: "memory", "cc");
return dst;
}
#endif
/*
*-----------------------------------------------------------------------------
*
* Div643232 --
*
* Unsigned integer division:
* The dividend is 64-bit wide
* The divisor is 32-bit wide
* The quotient is 32-bit wide
*
* Use this function if you are certain that the quotient will fit in 32 bits,
* If that is not the case, a #DE exception was generated in 32-bit version,
* but not in this 64-bit version. So please be careful.
*
* Results:
* Quotient and remainder
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__) || defined(_MSC_VER)
static INLINE void
Div643232(uint64 dividend, // IN
uint32 divisor, // IN
uint32 *quotient, // OUT
uint32 *remainder) // OUT
{
*quotient = (uint32)(dividend / divisor);
*remainder = (uint32)(dividend % divisor);
}
#endif
/*
*-----------------------------------------------------------------------------
*
* Div643264 --
*
* Unsigned integer division:
* The dividend is 64-bit wide
* The divisor is 32-bit wide
* The quotient is 64-bit wide
*
* Results:
* Quotient and remainder
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
#if defined(__GNUC__)
static INLINE void
Div643264(uint64 dividend, // IN
uint32 divisor, // IN
uint64 *quotient, // OUT
uint32 *remainder) // OUT
{
*quotient = dividend / divisor;
*remainder = dividend % divisor;
}
#endif
#endif // _VM_BASIC_ASM_X86_64_H_

View File

@@ -0,0 +1,752 @@
/*********************************************************
* Copyright (C) 2003-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* 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 REGENTS 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 REGENTS 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.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* vm_basic_defs.h --
*
* Standard macros for VMware source code.
*/
#ifndef _VM_BASIC_DEFS_H_
#define _VM_BASIC_DEFS_H_
#include "vm_basic_types.h" // For INLINE.
/* Checks for FreeBSD, filtering out VMKERNEL. */
#define __IS_FREEBSD__ (!defined(VMKERNEL) && defined(__FreeBSD__))
#define __IS_FREEBSD_VER__(ver) (__IS_FREEBSD__ && __FreeBSD_version >= (ver))
#if defined _WIN32 && defined USERLEVEL
#include <stddef.h> /*
* We redefine offsetof macro from stddef; make
* sure that it's already defined before we do that.
*/
#include <windows.h> // for Sleep() and LOWORD() etc.
#undef GetFreeSpace // Unpollute preprocessor namespace.
#endif
/*
* Simple macros
*/
#if (defined __APPLE__ || defined __FreeBSD__) && \
(!defined KERNEL && !defined _KERNEL && !defined VMKERNEL && !defined __KERNEL__)
# include <stddef.h>
#else
// XXX the _WIN32 one matches that of VC++, to prevent redefinition warning
// XXX the other one matches that of gcc3.3.3/glibc2.2.4 to prevent redefinition warnings
#ifndef offsetof
#define VMW_DEFINED_OFFSETOF
#ifdef _WIN32
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#endif
#endif // __APPLE__
/*
* This is necessary until we eliminate the inclusion of <windows.h> above.
* At that time, it should be possible to use "offsetof" everywhere.
*/
#ifndef vmw_offsetof
#define vmw_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#define VMW_CONTAINER_OF(ptr, type, member) \
((type *)((char *)(ptr) - vmw_offsetof(type, member)))
#ifndef ARRAYSIZE
#define ARRAYSIZE(a) (sizeof (a) / sizeof *(a))
#endif
#ifndef MIN
#define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))
#endif
/* The Solaris 9 cross-compiler complains about these not being used */
#ifndef sun
static INLINE int
Min(int a, int b)
{
return a < b ? a : b;
}
#endif
#ifndef MAX
#define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b))
#endif
#ifndef sun
static INLINE int
Max(int a, int b)
{
return a > b ? a : b;
}
#endif
#define VMW_CLAMP(x, min, max) \
((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
#define ROUNDUP(x,y) (((x) + (y) - 1) / (y) * (y))
#define ROUNDDOWN(x,y) ((x) / (y) * (y))
#define ROUNDUPBITS(x, bits) (((uintptr_t) (x) + MASK(bits)) & ~MASK(bits))
#define ROUNDDOWNBITS(x, bits) ((uintptr_t) (x) & ~MASK(bits))
#define CEILING(x, y) (((x) + (y) - 1) / (y))
#if defined __APPLE__
#include <machine/param.h>
#undef MASK
#endif
/*
* The MASK macro behaves badly when given negative numbers or numbers larger
* than the highest order bit number (e.g. 32 on a 32-bit machine) as an
* argument. The range 0..31 is safe.
*/
#define MASK(n) ((1 << (n)) - 1) /* make an n-bit mask */
#define MASK64(n) ((CONST64U(1) << (n)) - 1) /* make an n-bit mask */
/*
* MASKRANGE64 makes a bit vector starting at bit lo and ending at bit hi. No
* checking for lo < hi is done.
*/
#define MASKRANGE64(hi, lo) (MASK64((hi) - (lo) + 1) << (lo))
/* SIGNEXT64 sign extends a n-bit value to 64-bits. */
#define SIGNEXT64(val, n) (((int64)(val) << (64 - (n))) >> (64 - (n)))
#define DWORD_ALIGN(x) ((((x) + 3) >> 2) << 2)
#define QWORD_ALIGN(x) ((((x) + 7) >> 3) << 3)
#define IMPLIES(a,b) (!(a) || (b))
/*
* Not everybody (e.g., the monitor) has NULL
*/
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
/*
* Token concatenation
*
* The C preprocessor doesn't prescan arguments when they are
* concatenated or stringified. So we need extra levels of
* indirection to convince the preprocessor to expand its
* arguments.
*/
#define CONC(x, y) x##y
#define XCONC(x, y) CONC(x, y)
#define XXCONC(x, y) XCONC(x, y)
#define MAKESTR(x) #x
#define XSTR(x) MAKESTR(x)
/*
* Wide versions of string constants.
*/
#ifndef WSTR
#define WSTR_(X) L ## X
#define WSTR(X) WSTR_(X)
#endif
/*
* Page operations
*
* It has been suggested that these definitions belong elsewhere
* (like x86types.h). However, I deem them common enough
* (since even regular user-level programs may want to do
* page-based memory manipulation) to be here.
* -- edward
*/
#ifndef PAGE_SHIFT // {
#if defined VM_I386
#define PAGE_SHIFT 12
#elif defined __APPLE__
#define PAGE_SHIFT 12
#elif defined __arm__
#define PAGE_SHIFT 12
#else
#error
#endif
#endif // }
#ifndef PAGE_SIZE
#define PAGE_SIZE (1<<PAGE_SHIFT)
#endif
#ifndef PAGE_MASK
#define PAGE_MASK (PAGE_SIZE - 1)
#endif
#ifndef PAGE_OFFSET
#define PAGE_OFFSET(_addr) ((uintptr_t)(_addr)&(PAGE_SIZE-1))
#endif
#ifndef VM_PAGE_BASE
#define VM_PAGE_BASE(_addr) ((_addr)&~(PAGE_SIZE-1))
#endif
#ifndef VM_PAGES_SPANNED
#define VM_PAGES_SPANNED(_addr, _size) \
((((_addr) & (PAGE_SIZE - 1)) + (_size) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
#endif
#ifndef BYTES_2_PAGES
#define BYTES_2_PAGES(_nbytes) ((_nbytes) >> PAGE_SHIFT)
#endif
#ifndef PAGES_2_BYTES
#define PAGES_2_BYTES(_npages) (((uint64)(_npages)) << PAGE_SHIFT)
#endif
#ifndef MBYTES_2_PAGES
#define MBYTES_2_PAGES(_nbytes) ((_nbytes) << (20 - PAGE_SHIFT))
#endif
#ifndef PAGES_2_MBYTES
#define PAGES_2_MBYTES(_npages) ((_npages) >> (20 - PAGE_SHIFT))
#endif
#ifndef GBYTES_2_PAGES
#define GBYTES_2_PAGES(_nbytes) ((_nbytes) << (30 - PAGE_SHIFT))
#endif
#ifndef PAGES_2_GBYTES
#define PAGES_2_GBYTES(_npages) ((_npages) >> (30 - PAGE_SHIFT))
#endif
#ifndef BYTES_2_MBYTES
#define BYTES_2_MBYTES(_nbytes) ((_nbytes) >> 20)
#endif
#ifndef MBYTES_2_BYTES
#define MBYTES_2_BYTES(_nbytes) ((uint64)(_nbytes) << 20)
#endif
#ifndef BYTES_2_GBYTES
#define BYTES_2_GBYTES(_nbytes) ((_nbytes) >> 30)
#endif
#ifndef GBYTES_2_BYTES
#define GBYTES_2_BYTES(_nbytes) ((uint64)(_nbytes) << 30)
#endif
#ifndef VM_PAE_LARGE_PAGE_SHIFT
#define VM_PAE_LARGE_PAGE_SHIFT 21
#endif
#ifndef VM_PAE_LARGE_PAGE_SIZE
#define VM_PAE_LARGE_PAGE_SIZE (1 << VM_PAE_LARGE_PAGE_SHIFT)
#endif
#ifndef VM_PAE_LARGE_PAGE_MASK
#define VM_PAE_LARGE_PAGE_MASK (VM_PAE_LARGE_PAGE_SIZE - 1)
#endif
#ifndef VM_PAE_LARGE_2_SMALL_PAGES
#define VM_PAE_LARGE_2_SMALL_PAGES (BYTES_2_PAGES(VM_PAE_LARGE_PAGE_SIZE))
#endif
/*
* Word operations
*/
#ifndef LOWORD
#define LOWORD(_dw) ((_dw) & 0xffff)
#endif
#ifndef HIWORD
#define HIWORD(_dw) (((_dw) >> 16) & 0xffff)
#endif
#ifndef LOBYTE
#define LOBYTE(_w) ((_w) & 0xff)
#endif
#ifndef HIBYTE
#define HIBYTE(_w) (((_w) >> 8) & 0xff)
#endif
#define HIDWORD(_qw) ((uint32)((_qw) >> 32))
#define LODWORD(_qw) ((uint32)(_qw))
#define QWORD(_hi, _lo) ((((uint64)(_hi)) << 32) | ((uint32)(_lo)))
/*
* Deposit a field _src at _pos bits from the right,
* with a length of _len, into the integer _target.
*/
#define DEPOSIT_BITS(_src,_pos,_len,_target) { \
unsigned mask = ((1 << _len) - 1); \
unsigned shiftedmask = ((1 << _len) - 1) << _pos; \
_target = (_target & ~shiftedmask) | ((_src & mask) << _pos); \
}
/*
* Get return address.
*/
#ifdef _MSC_VER
#ifdef __cplusplus
extern "C"
#endif
void *_ReturnAddress(void);
#pragma intrinsic(_ReturnAddress)
#define GetReturnAddress() _ReturnAddress()
#elif __GNUC__
#define GetReturnAddress() __builtin_return_address(0)
#endif
#ifdef __GNUC__
#ifndef sun
/*
* A bug in __builtin_frame_address was discovered in gcc 4.1.1, and
* fixed in 4.2.0; assume it originated in 4.0. PR 147638 and 554369.
*/
#if !(__GNUC__ == 4 && (__GNUC_MINOR__ == 0 || __GNUC_MINOR__ == 1))
#define GetFrameAddr() __builtin_frame_address(0)
#endif
#endif // sun
#endif // __GNUC__
/*
* Data prefetch was added in gcc 3.1.1
* http://www.gnu.org/software/gcc/gcc-3.1/changes.html
*/
#ifdef __GNUC__
# if ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 1) || \
(__GNUC__ == 3 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ >= 1))
# define PREFETCH_R(var) __builtin_prefetch((var), 0 /* read */, \
3 /* high temporal locality */)
# define PREFETCH_W(var) __builtin_prefetch((var), 1 /* write */, \
3 /* high temporal locality */)
# else
# define PREFETCH_R(var) ((void)(var))
# define PREFETCH_W(var) ((void)(var))
# endif
#endif /* __GNUC__ */
#ifdef USERLEVEL // {
/*
* Note this might be a problem on NT b/c while sched_yield guarantees it
* moves you to the end of your priority list, Sleep(0) offers no such
* guarantee. Bummer. --Jeremy.
*/
#if defined(N_PLAT_NLM)
/* We do not have YIELD() as we do not need it yet... */
#elif defined(_WIN32)
# define YIELD() Sleep(0)
#elif defined(VMKERNEL)
/* We don't have a YIELD macro in the vmkernel */
#else
# include <sched.h> // For sched_yield. Don't ask. --Jeremy.
# define YIELD() sched_yield()
#endif
/*
* Standardize some Posix names on Windows.
*/
#ifdef _WIN32 // {
#define snprintf _snprintf
#define strtok_r strtok_s
#if (_MSC_VER < 1500)
#define vsnprintf _vsnprintf
#endif
typedef int uid_t;
typedef int gid_t;
static INLINE void
sleep(unsigned int sec)
{
Sleep(sec * 1000);
}
static INLINE int
usleep(unsigned long usec)
{
Sleep(CEILING(usec, 1000));
return 0;
}
typedef int pid_t;
#define F_OK 0
#define X_OK 1
#define W_OK 2
#define R_OK 4
#endif // }
/*
* Macro for username comparison.
*/
#ifdef _WIN32 // {
#define USERCMP(x,y) Str_Strcasecmp(x,y)
#else
#define USERCMP(x,y) strcmp(x,y)
#endif // }
#endif // }
#ifndef va_copy
#ifdef _WIN32
/*
* Windows needs va_copy. This works for both 32 and 64-bit Windows
* based on inspection of how varags.h from the Visual C CRTL is
* implemented. (Future versions of the RTL may break this).
*/
#define va_copy(dest, src) ((dest) = (src))
#elif defined(__APPLE__) && defined(KERNEL)
#include "availabilityMacOS.h"
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
// The Mac OS 10.5 kernel SDK defines va_copy in stdarg.h.
#include <stdarg.h>
#else
/*
* The Mac OS 10.4 kernel SDK needs va_copy. Based on inspection of
* stdarg.h from the MacOSX10.4u.sdk kernel framework, this should
* work.
*/
#define va_copy(dest, src) ((dest) = (src))
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
#elif defined(__GNUC__) && (__GNUC__ < 3)
/*
* Old versions of gcc recognize __va_copy, but not va_copy.
*/
#define va_copy(dest, src) __va_copy(dest, src)
#endif // _WIN32
#endif // va_copy
/*
* This one is outside USERLEVEL because it's used by
* files compiled into the Windows hgfs driver or the display
* driver.
*/
#ifdef _WIN32
#define PATH_MAX 256
#ifndef strcasecmp
#define strcasecmp(_s1,_s2) _stricmp((_s1),(_s2))
#endif
#ifndef strncasecmp
#define strncasecmp(_s1,_s2,_n) _strnicmp((_s1),(_s2),(_n))
#endif
#endif
#if defined __linux__ && !defined __KERNEL__ && !defined MODULE && \
!defined VMM && !defined FROBOS && !defined __ANDROID__
#include <features.h>
#if __GLIBC_PREREQ(2, 1) && !defined GLIBC_VERSION_21
#define GLIBC_VERSION_21
#endif
#if __GLIBC_PREREQ(2, 2) && !defined GLIBC_VERSION_22
#define GLIBC_VERSION_22
#endif
#if __GLIBC_PREREQ(2, 3) && !defined GLIBC_VERSION_23
#define GLIBC_VERSION_23
#endif
#if __GLIBC_PREREQ(2, 4) && !defined GLIBC_VERSION_24
#define GLIBC_VERSION_24
#endif
#if __GLIBC_PREREQ(2, 5) && !defined GLIBC_VERSION_25
#define GLIBC_VERSION_25
#endif
#if __GLIBC_PREREQ(2, 12) && !defined GLIBC_VERSION_212
#define GLIBC_VERSION_212
#endif
#endif
/*
* Convenience macros and definitions. Can often be used instead of #ifdef.
*/
#undef DEBUG_ONLY
#ifdef VMX86_DEBUG
#define vmx86_debug 1
#define DEBUG_ONLY(x) x
#else
#define vmx86_debug 0
#define DEBUG_ONLY(x)
#endif
#ifdef VMX86_STATS
#define vmx86_stats 1
#define STATS_ONLY(x) x
#else
#define vmx86_stats 0
#define STATS_ONLY(x)
#endif
#ifdef VMX86_DEVEL
#define vmx86_devel 1
#define DEVEL_ONLY(x) x
#else
#define vmx86_devel 0
#define DEVEL_ONLY(x)
#endif
#ifdef VMX86_LOG
#define vmx86_log 1
#define LOG_ONLY(x) x
#else
#define vmx86_log 0
#define LOG_ONLY(x)
#endif
#ifdef VMX86_BETA
#define vmx86_beta 1
#define BETA_ONLY(x) x
#else
#define vmx86_beta 0
#define BETA_ONLY(x)
#endif
#ifdef VMX86_RELEASE
#define vmx86_release 1
#define RELEASE_ONLY(x) x
#else
#define vmx86_release 0
#define RELEASE_ONLY(x)
#endif
#ifdef VMX86_SERVER
#define vmx86_server 1
#define SERVER_ONLY(x) x
#define HOSTED_ONLY(x)
#else
#define vmx86_server 0
#define SERVER_ONLY(x)
#define HOSTED_ONLY(x) x
#endif
#ifdef VMKERNEL
#define vmkernel 1
#define VMKERNEL_ONLY(x) x
#else
#define vmkernel 0
#define VMKERNEL_ONLY(x)
#endif
#ifdef _WIN32
#define WIN32_ONLY(x) x
#define POSIX_ONLY(x)
#define vmx86_win32 1
#else
#define WIN32_ONLY(x)
#define POSIX_ONLY(x) x
#define vmx86_win32 0
#endif
#ifdef __linux__
#define vmx86_linux 1
#define LINUX_ONLY(x) x
#else
#define vmx86_linux 0
#define LINUX_ONLY(x)
#endif
#ifdef __APPLE__
#define vmx86_apple 1
#define APPLE_ONLY(x) x
#else
#define vmx86_apple 0
#define APPLE_ONLY(x)
#endif
#ifdef VMM
#define VMM_ONLY(x) x
#define USER_ONLY(x)
#else
#define VMM_ONLY(x)
#define USER_ONLY(x) x
#endif
/* VMVISOR ifdef only allowed in the vmkernel */
#ifdef VMKERNEL
#ifdef VMVISOR
#define vmvisor 1
#define VMVISOR_ONLY(x) x
#else
#define vmvisor 0
#define VMVISOR_ONLY(x)
#endif
#endif
#ifdef _WIN32
#define VMW_INVALID_HANDLE INVALID_HANDLE_VALUE
#else
#define VMW_INVALID_HANDLE (-1LL)
#endif
#ifdef _WIN32
#define fsync(fd) _commit(fd)
#define fileno(f) _fileno(f)
#else
#endif
/*
* Debug output macros for Windows drivers (the Eng variant is for
* display/printer drivers only.
*/
#ifdef _WIN32
#ifndef USES_OLD_WINDDK
#if defined(VMX86_LOG)
#ifdef _WIN64
#define WinDrvPrint(arg, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, (ULONG)~0, arg, __VA_ARGS__)
#else
#define WinDrvPrint(arg, ...) DbgPrint(arg, __VA_ARGS__)
#endif
#define WinDrvEngPrint(arg, ...) EngDbgPrint(arg, __VA_ARGS__)
#else
#define WinDrvPrint(arg, ...)
#define WinDrvEngPrint(arg, ...)
#endif
#endif
#endif // _WIN32
#ifdef HOSTED_LG_PG
#define hosted_lg_pg 1
#else
#define hosted_lg_pg 0
#endif
/*
* Use to initialize cbSize for this structure to preserve < Vista
* compatibility.
*/
#define NONCLIENTMETRICSINFO_V1_SIZE CCSIZEOF_STRUCT(NONCLIENTMETRICS, \
lfMessageFont)
/* This is not intended to be thread-safe. */
#define DO_ONCE(code) \
do { \
static Bool _doOnceDone = FALSE; \
if (UNLIKELY(!_doOnceDone)) { \
_doOnceDone = TRUE; \
code; \
} \
} while (0)
/*
* Bug 827422 and 838523.
*/
#if defined __GNUC__ && __GNUC__ >= 4
#define VISIBILITY_HIDDEN __attribute__((visibility("hidden")))
#else
#define VISIBILITY_HIDDEN /* nothing */
#endif
/*
* Bitfield extraction.
*/
#define EXTRACT_BITSLICE32(_val , _lsb, _msb) \
(((uint32)(_val) << (31 - (_msb))) >> ((31 - (_msb)) + (_lsb)))
#define EXTRACT_BITFIELD32(_val, _pos, _len) \
EXTRACT_BITSLICE32((_val), (_pos), ((_pos) + (_len) - 1))
#define EXTRACT_BITSLICE64(_val, _lsb, _msb) \
(((uint64)(_val) << (63 - (_msb))) >> ((63 - (_msb)) + (_lsb)))
#define EXTRACT_BITFIELD64(_val, _pos, _len) \
EXTRACT_BITSLICE64((_val), (_pos), ((_pos) + (_len) - 1))
/*
* Typical cache line size. Use this for aligning structures to cache
* lines for performance, but do not rely on it for correctness.
*/
#define CACHELINE_SIZE 64
#define CACHELINE_ALIGNMENT_MASK (CACHELINE_SIZE - 1)
#endif // ifndef _VM_BASIC_DEFS_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
/*********************************************************
* Copyright (C) 2006-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* vmcheck.h --
*
* Utility functions for discovering our virtualization status.
*/
#ifndef __VMCHECK_H__
# define __VMCHECK_H__
#ifdef __cplusplus
extern "C" {
#endif
# include "vm_basic_types.h"
Bool
VmCheck_GetVersion(uint32 *version, // OUT
uint32 *type); // OUT
Bool
VmCheck_IsVirtualWorld(void);
#ifdef __cplusplus
}
#endif
#endif /* __VMCHECK_H__ */

View File

@@ -0,0 +1,37 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* vmsignal.h --
*
* Posix signal handling utility functions
*
*/
#ifndef __VMSIGNAL_H__
# define __VMSIGNAL_H__
#include <signal.h>
int Signal_SetGroupHandler(int const *signals, struct sigaction *olds, unsigned int nr, void (*handler)(int signal));
int Signal_ResetGroupHandler(int const *signals, struct sigaction const *olds, unsigned int nr);
#endif /* __VMSIGNAL_H__ */

View File

@@ -0,0 +1,87 @@
/*********************************************************
* Copyright (C) 2003-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* 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 REGENTS 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 REGENTS 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.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* vmware.h --
*
* Standard include file for VMware source code.
*/
#ifndef _VMWARE_H_
#define _VMWARE_H_
#include "vm_basic_types.h"
#include "vm_basic_defs.h"
#include "vm_assert.h"
/*
* Global error codes. Currently used internally, but may be exported
* to customers one day, like VM_E_XXX in vmcontrol_constants.h
*/
typedef enum VMwareStatus {
VMWARE_STATUS_SUCCESS, /* success */
VMWARE_STATUS_ERROR, /* generic error */
VMWARE_STATUS_NOMEM, /* generic memory allocation error */
VMWARE_STATUS_INSUFFICIENT_RESOURCES, /* internal or system resource limit exceeded */
VMWARE_STATUS_INVALID_ARGS /* invalid arguments */
} VMwareStatus;
#define VMWARE_SUCCESS(s) ((s) == VMWARE_STATUS_SUCCESS)
#endif // ifndef _VMWARE_H_

View File

@@ -0,0 +1,57 @@
/*********************************************************
* Copyright (C) 2002-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* vmware_pack_begin.h --
*
* Begin of structure packing. See vmware_pack_init.h for details.
*
* Note that we do not use the following construct in this include file,
* because we want to emit the code every time the file is included --hpreg
*
* #ifndef foo
* # define foo
* ...
* #endif
*
*/
#include "vmware_pack_init.h"
#ifdef _MSC_VER
# pragma pack(push, 1)
#elif __GNUC__
#else
# error Compiler packing...
#endif

View File

@@ -0,0 +1,58 @@
/*********************************************************
* Copyright (C) 2002-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* vmware_pack_end.h --
*
* End of structure packing. See vmware_pack_init.h for details.
*
* Note that we do not use the following construct in this include file,
* because we want to emit the code every time the file is included --hpreg
*
* #ifndef foo
* # define foo
* ...
* #endif
*
*/
#include "vmware_pack_init.h"
#ifdef _MSC_VER
# pragma pack(pop)
#elif __GNUC__
__attribute__((__packed__))
#else
# error Compiler packing...
#endif

View File

@@ -0,0 +1,79 @@
/*********************************************************
* Copyright (C) 2002-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
#ifndef __VMWARE_PACK_INIT_H__
# define __VMWARE_PACK_INIT_H__
/*
* vmware_pack_init.h --
*
* Platform-independent code to make the compiler pack (i.e. have them
* occupy the smallest possible space) structure definitions. The following
* constructs are known to work --hpreg
*
* #include "vmware_pack_begin.h"
* struct foo {
* ...
* }
* #include "vmware_pack_end.h"
* ;
*
* typedef
* #include "vmware_pack_begin.h"
* struct foo {
* ...
* }
* #include "vmware_pack_end.h"
* foo;
*/
#ifdef _MSC_VER
/*
* MSVC 6.0 emits warning 4103 when the pack push and pop pragma pairing is
* not balanced within 1 included file. That is annoying because our scheme
* is based on the pairing being balanced between 2 included files.
*
* So we disable this warning, but this is safe because the compiler will also
* emit warning 4161 when there is more pops than pushes within 1 main
* file --hpreg
*/
# pragma warning(disable:4103)
#elif __GNUC__
#else
# error Compiler packing...
#endif
#endif /* __VMWARE_PACK_INIT_H__ */

View File

@@ -0,0 +1,243 @@
/*********************************************************
* Copyright (C) 2006-2013 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*
* x86_basic_defs.h --
*
* Basic macros describing the x86 architecture.
*/
#ifndef _X86_BASIC_DEFS_H_
#define _X86_BASIC_DEFS_H_
#define SIZE_8BIT 1
#define SIZE_16BIT 2
#define SIZE_24BIT 3
#define SIZE_32BIT 4
#define SIZE_48BIT 6
#define SIZE_64BIT 8
#define SIZE_80BIT 10
#define SIZE_128BIT 16
#define SIZE_256BIT 32
#define X86_MAX_INSTR_LEN 15 /* Max byte length of an x86 instruction. */
#define NUM_IDT_VECTORS 256
/*
* control registers
*/
#define CR0_PE 0x00000001
#define CR0_MP 0x00000002
#define CR0_EM 0x00000004
#define CR0_TS 0x00000008
#define CR0_ET 0x00000010
#define CR0_NE 0x00000020
#define CR0_WP 0x00010000
#define CR0_AM 0x00040000
#define CR0_NW 0x20000000
#define CR0_CD 0x40000000
#define CR0_PG 0x80000000
#define CR0_RESERVED CONST64U(0xffffffff1ffaffc0)
#define CR3_PWT 0x00000008
#define CR3_PCD 0x00000010
#define CR3_PDB_SHIFT 12
#define CR3_PDB_MASK 0xfffff000
#define CR3_IGNORE 0xFFF
#define PAE_CR3_IGNORE 0x1F
#define CR3_PCID_MASK 0xFFF
#define CR3_NO_FLUSH (1ULL << 63)
#define CR4_VME 0x00000001
#define CR4_PVI 0x00000002
#define CR4_TSD 0x00000004
#define CR4_DE 0x00000008
#define CR4_PSE 0x00000010
#define CR4_PAE 0x00000020
#define CR4_MCE 0x00000040
#define CR4_PGE 0x00000080
#define CR4_PCE 0x00000100
#define CR4_OSFXSR 0x00000200 // CPU/OS supports SIMD insts
#define CR4_OSXMMEXCPT 0x00000400 // #XF exception enable PIII only
#define CR4_VMXE 0x00002000
#define CR4_SMXE 0x00004000
#define CR4_FSGSBASE 0x00010000
#define CR4_PCIDE 0x00020000
#define CR4_OSXSAVE 0x00040000
#define CR4_SMEP 0x00100000
#define CR4_SMAP 0x00200000
/* Removing a bit from CR4_RESERVED causes Task_Switch to leave the bit set. */
#define CR4_RESERVED CONST64U(0xffffffffffc89800)
#define CR8_RESERVED CONST64U(0xfffffffffffffff0)
/*
* Debug registers.
*/
#define DR_COUNT 4
#define DR6_B0 0x00000001
#define DR6_B1 0x00000002
#define DR6_B2 0x00000004
#define DR6_B3 0x00000008
#define DR6_B0123 (DR6_B0 | DR6_B1 | DR6_B2 | DR6_B3)
#define DR6_B(_n) (1 << (_n))
#define DR6_BD 0x00002000
#define DR6_BS 0x00004000
#define DR6_BT 0x00008000
#define DR6_RTM 0x00010000
#define DR6_ONES 0xfffe0ff0
#define DR6_DEFAULT (DR6_ONES | DR6_RTM)
#define DR6_RESERVED_MASK 0xfffe1ff0
#define DR7_L_MASK(_n) (1 << ((_n) * 2))
#define DR7_G_MASK(_n) (1 << ((_n) * 2 + 1))
#define DR7_LG_MASK(_n) (3 << ((_n) * 2))
#define DR7_RW_MASK(_n) (3 << (16 + (_n) * 4))
#define DR7_LEN_MASK(_n) (3 << (18 + (_n) * 4))
#define DR7_BP_MASK(_n) (DR7_L_MASK(_n) |\
DR7_G_MASK(_n) |\
DR7_RW_MASK(_n) |\
DR7_LEN_MASK(_n))
#define DR7_L0 DR7_L_MASK(0)
#define DR7_G0 DR7_G_MASK(0)
#define DR7_L1 DR7_L_MASK(1)
#define DR7_G1 DR7_G_MASK(1)
#define DR7_L2 DR7_L_MASK(2)
#define DR7_G2 DR7_G_MASK(2)
#define DR7_L3 DR7_L_MASK(3)
#define DR7_G3 DR7_G_MASK(3)
#define DR7_ENABLED 0x000000ff
#define DR7_LE 0x00000100 // Deprecated in modern hardware
#define DR7_GE 0x00000200 // Deprecated in modern hardware
#define DR7_GD 0x00002000
#define DR7_ONES 0x00000400
#define DR7_RTM 0x00000800
#define DR7_RESERVED CONST64U(0xffffffff0000d400)
#define DR7_DEFUNCT (DR7_LE | DR7_GE)
#define DR7_DEFAULT DR7_ONES
#define DR7_LX_MASK (DR7_L0 | DR7_L1 | DR7_L2 | DR7_L3 | DR7_LE)
#define DR7_GX_MASK (DR7_G0 | DR7_G1 | DR7_G2 | DR7_G3 | DR7_GE)
#define DR7_LGX_MASK (DR7_LX_MASK | DR7_GX_MASK)
#define DR7_RW(_r,_n) (((_r) >> (16+(_n)*4)) & 0x3)
#define DR7_L(_r,_n) (((_r) >> ((_n)*2)) & 1)
#define DR7_G(_r,_n) (((_r) >> (1 + (_n)*2)) & 1)
#define DR7_LEN(_r,_n) (((_r) >> (18+(_n)*4)) & 0x3)
#define DR7_RW_BITS(_n,_rw) ((_rw) << (16 + (_n) * 4))
#define DR7_LEN_BITS(_n,_len) ((_len) << (18 + (_n) * 4))
#define DR7_RW_INST 0x0
#define DR7_RW_WRITES 0x1
#define DR7_RW_IO 0x2
#define DR7_RW_ACCESS 0x3
#define DR7_LENGTH_1 0x0
#define DR7_LENGTH_2 0x1
#define DR7_LENGTH_8 0x2
#define DR7_LENGTH_4 0x3
#define DEBUG_STATUS_B0 (1<<0)
#define DEBUG_STATUS_B1 (1<<1)
#define DEBUG_STATUS_B2 (1<<2)
#define DEBUG_STATUS_B3 (1<<3)
#define DEBUG_STATUS_DB (1<<13)
#define DEBUG_STATUS_BS (1<<14)
#define DEBUG_STATUS_BT (1<<15)
/*
* exception error codes
*/
#define EXC_DE 0
#define EXC_DB 1
#define EXC_NMI 2
#define EXC_BP 3
#define EXC_OF 4
#define EXC_BR 5
#define EXC_UD 6
#define EXC_NM 7
#define EXC_DF 8
#define EXC_TS 10
#define EXC_NP 11
#define EXC_SS 12
#define EXC_GP 13
#define EXC_PF 14
#define EXC_MF 16
#define EXC_AC 17
#define EXC_MC 18
#define EXC_XF 19 /* SIMD exception. */
#define EXC_SX 30 /* Security exception (SVM only). */
/*
* eflag/rflag definitions.
*/
#define EFLAGS_IOPL_SHIFT 12
typedef enum x86_FLAGS {
EFLAGS_NONE = 0,
EFLAGS_CF = (1 << 0), /* User */
EFLAGS_SET = (1 << 1),
EFLAGS_PF = (1 << 2), /* User */
EFLAGS_AF = (1 << 4), /* User */
EFLAGS_ZF = (1 << 6), /* User */
EFLAGS_SF = (1 << 7), /* User */
EFLAGS_TF = (1 << 8), /* Priv */
EFLAGS_IF = (1 << 9), /* Priv */
EFLAGS_DF = (1 << 10), /* User */
EFLAGS_OF = (1 << 11), /* User */
EFLAGS_NT = (1 << 14), /* Priv */
EFLAGS_RF = (1 << 16), /* Priv */
EFLAGS_VM = (1 << 17), /* Priv */
EFLAGS_AC = (1 << 18), /* Priv */
EFLAGS_VIF = (1 << 19), /* Priv */
EFLAGS_VIP = (1 << 20), /* Priv */
EFLAGS_ID = (1 << 21), /* Priv */
EFLAGS_IOPL = 3 << EFLAGS_IOPL_SHIFT,
EFLAGS_ARITH = (EFLAGS_CF | EFLAGS_PF | EFLAGS_AF | EFLAGS_ZF |
EFLAGS_SF | EFLAGS_OF),
EFLAGS_USER = (EFLAGS_CF | EFLAGS_PF | EFLAGS_AF | EFLAGS_ZF |
EFLAGS_SF | EFLAGS_DF | EFLAGS_OF),
EFLAGS_PRIV = (EFLAGS_TF | EFLAGS_IF | EFLAGS_IOPL | EFLAGS_NT |
EFLAGS_RF | EFLAGS_VM | EFLAGS_AC | EFLAGS_VIF |
EFLAGS_VIP | EFLAGS_ID),
EFLAGS_ALL = (EFLAGS_CF | EFLAGS_PF | EFLAGS_AF | EFLAGS_ZF |
EFLAGS_SF | EFLAGS_DF | EFLAGS_OF | EFLAGS_TF |
EFLAGS_IF | EFLAGS_IOPL | EFLAGS_NT | EFLAGS_RF |
EFLAGS_VM | EFLAGS_AC | EFLAGS_VIF | EFLAGS_VIP |
EFLAGS_ID),
EFLAGS_ALL_16 = EFLAGS_ALL & 0xffff,
EFLAGS_REAL_32 = (EFLAGS_ALL & ~(EFLAGS_VIP | EFLAGS_VIF | EFLAGS_VM)),
EFLAGS_V8086_32 = (EFLAGS_ALL & ~(EFLAGS_VIP | EFLAGS_VIF |
EFLAGS_VM | EFLAGS_IOPL)),
EFLAGS_REAL_16 = EFLAGS_REAL_32 & 0xffff,
EFLAGS_V8086_16 = EFLAGS_V8086_32 & 0xffff,
EFLAGS_CLEAR_ON_EXC = (EFLAGS_TF | EFLAGS_VM | EFLAGS_RF | EFLAGS_NT),
EFLAGS__4 = 0x7fffffff /* ensure 4 byte encoding */
} x86_FLAGS;
#endif // ifndef _VM_BASIC_DEFS_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,455 @@
/*********************************************************
* Copyright (C) 2003-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
/*
* x86cpuid_asm.h
*
* CPUID-related assembly functions.
*/
#ifndef _X86CPUID_ASM_H_
#define _X86CPUID_ASM_H_
#include "vm_basic_asm.h"
#include "x86cpuid.h"
/*
* x86-64 windows doesn't support inline asm so we have to use these
* intrinsic functions defined in the compiler. Not all of these are well
* documented. There is an array in the compiler dll (c1.dll) which has
* an array of the names of all the intrinsics minus the leading
* underscore. Searching around in the ntddk.h file can also be helpful.
*
* The declarations for the intrinsic functions were taken from the DDK.
* Our declarations must match the ddk's otherwise the 64-bit c++ compiler
* will complain about second linkage of the intrinsic functions.
* We define the intrinsic using the basic types corresponding to the
* Windows typedefs. This avoids having to include windows header files
* to get to the windows types.
*/
#ifdef _MSC_VER
#ifdef __cplusplus
extern "C" {
#endif
#ifdef VM_X86_64
/*
* intrinsic functions only supported by x86-64 windows as of 2k3sp1
*/
void __cpuid(int regs[4], int eax);
#pragma intrinsic(__cpuid)
#endif /* VM_X86_64 */
#ifdef __cplusplus
}
#endif
#endif /* _MSC_VER */
#ifdef __GNUC__ // {
/*
* Checked against the Intel manual and GCC --hpreg
*
* Need __volatile__ and "memory" since CPUID has a synchronizing effect.
* The CPUID may also change at runtime (APIC flag, etc).
*
*/
/*
* %ebx is reserved on i386 PIC. Apple's gcc-5493 (gcc 4.0) compiling
* for x86_64 incorrectly errors out saying %ebx is reserved. This is
* Apple bug 7304232.
*/
#if vm_x86_64 ? (defined __APPLE_CC__ && __APPLE_CC__ == 5493) : defined __PIC__
#if vm_x86_64
/*
* Note that this generates movq %rbx,%rbx; cpuid; xchgq %rbx,%rbx ...
* Unfortunately Apple's assembler does not have .ifnes, and I cannot
* figure out how to do that with .if. If we ever enable this code
* on other 64bit systems, both movq & xchgq should be surrounded by
* .ifnes \"%%rbx\", \"%q1\" & .endif
*/
#define VM_CPUID_BLOCK "movq %%rbx, %q1\n\t" \
"cpuid\n\t" \
"xchgq %%rbx, %q1\n\t"
#define VM_EBX_OUT(reg) "=&r"(reg)
#else
#define VM_CPUID_BLOCK "movl %%ebx, %1\n\t" \
"cpuid\n\t" \
"xchgl %%ebx, %1\n\t"
#define VM_EBX_OUT(reg) "=&rm"(reg)
#endif
#else
#define VM_CPUID_BLOCK "cpuid"
#define VM_EBX_OUT(reg) "=b"(reg)
#endif
static INLINE void
__GET_CPUID(int eax, // IN
CPUIDRegs *regs) // OUT
{
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (regs->eax), VM_EBX_OUT(regs->ebx), "=c" (regs->ecx), "=d" (regs->edx)
: "a" (eax)
: "memory"
);
}
static INLINE void
__GET_CPUID2(int eax, // IN
int ecx, // IN
CPUIDRegs *regs) // OUT
{
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (regs->eax), VM_EBX_OUT(regs->ebx), "=c" (regs->ecx), "=d" (regs->edx)
: "a" (eax), "c" (ecx)
: "memory"
);
}
static INLINE uint32
__GET_EAX_FROM_CPUID(int eax) // IN
{
uint32 ebx;
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (eax), VM_EBX_OUT(ebx)
: "a" (eax)
: "memory", "%ecx", "%edx"
);
return eax;
}
static INLINE uint32
__GET_EBX_FROM_CPUID(int eax) // IN
{
uint32 ebx;
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (eax), VM_EBX_OUT(ebx)
: "a" (eax)
: "memory", "%ecx", "%edx"
);
return ebx;
}
static INLINE uint32
__GET_ECX_FROM_CPUID(int eax) // IN
{
uint32 ecx;
uint32 ebx;
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (eax), VM_EBX_OUT(ebx), "=c" (ecx)
: "a" (eax)
: "memory", "%edx"
);
return ecx;
}
static INLINE uint32
__GET_EDX_FROM_CPUID(int eax) // IN
{
uint32 edx;
uint32 ebx;
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (eax), VM_EBX_OUT(ebx), "=d" (edx)
: "a" (eax)
: "memory", "%ecx"
);
return edx;
}
static INLINE uint32
__GET_EAX_FROM_CPUID4(int ecx) // IN
{
uint32 eax;
uint32 ebx;
__asm__ __volatile__(
VM_CPUID_BLOCK
: "=a" (eax), VM_EBX_OUT(ebx), "=c" (ecx)
: "a" (4), "c" (ecx)
: "memory", "%edx"
);
return eax;
}
#undef VM_CPUID_BLOCK
#undef VM_EBX_OUT
#elif defined(_MSC_VER) // } {
static INLINE void
__GET_CPUID(int input, CPUIDRegs *regs)
{
#ifdef VM_X86_64
__cpuid((int *)regs, input);
#else
__asm push esi
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, input
__asm mov esi, regs
__asm _emit 0x0f __asm _emit 0xa2
__asm mov 0x0[esi], eax
__asm mov 0x4[esi], ebx
__asm mov 0x8[esi], ecx
__asm mov 0xC[esi], edx
__asm pop edx
__asm pop ecx
__asm pop ebx
__asm pop esi
#endif
}
#ifdef VM_X86_64
/*
* No inline assembly in Win64. Implemented in bora/lib/misc in
* cpuidMasm64.asm.
*/
extern void
__GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs);
#else // VM_X86_64
static INLINE void
__GET_CPUID2(int inputEax, int inputEcx, CPUIDRegs *regs)
{
__asm push esi
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, inputEax
__asm mov ecx, inputEcx
__asm mov esi, regs
__asm _emit 0x0f __asm _emit 0xa2
__asm mov 0x0[esi], eax
__asm mov 0x4[esi], ebx
__asm mov 0x8[esi], ecx
__asm mov 0xC[esi], edx
__asm pop edx
__asm pop ecx
__asm pop ebx
__asm pop esi
}
#endif
static INLINE uint32
__GET_EAX_FROM_CPUID(int input)
{
#ifdef VM_X86_64
CPUIDRegs regs;
__cpuid((int *)&regs, input);
return regs.eax;
#else
uint32 output;
//NOT_TESTED();
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, input
__asm _emit 0x0f __asm _emit 0xa2
__asm mov output, eax
__asm pop edx
__asm pop ecx
__asm pop ebx
return output;
#endif
}
static INLINE uint32
__GET_EBX_FROM_CPUID(int input)
{
#ifdef VM_X86_64
CPUIDRegs regs;
__cpuid((int *)&regs, input);
return regs.ebx;
#else
uint32 output;
//NOT_TESTED();
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, input
__asm _emit 0x0f __asm _emit 0xa2
__asm mov output, ebx
__asm pop edx
__asm pop ecx
__asm pop ebx
return output;
#endif
}
static INLINE uint32
__GET_ECX_FROM_CPUID(int input)
{
#ifdef VM_X86_64
CPUIDRegs regs;
__cpuid((int *)&regs, input);
return regs.ecx;
#else
uint32 output;
//NOT_TESTED();
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, input
__asm _emit 0x0f __asm _emit 0xa2
__asm mov output, ecx
__asm pop edx
__asm pop ecx
__asm pop ebx
return output;
#endif
}
static INLINE uint32
__GET_EDX_FROM_CPUID(int input)
{
#ifdef VM_X86_64
CPUIDRegs regs;
__cpuid((int *)&regs, input);
return regs.edx;
#else
uint32 output;
//NOT_TESTED();
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, input
__asm _emit 0x0f __asm _emit 0xa2
__asm mov output, edx
__asm pop edx
__asm pop ecx
__asm pop ebx
return output;
#endif
}
#ifdef VM_X86_64
/*
* No inline assembly in Win64. Implemented in bora/lib/misc in
* cpuidMasm64.asm.
*/
extern uint32
__GET_EAX_FROM_CPUID4(int inputEcx);
#else // VM_X86_64
static INLINE uint32
__GET_EAX_FROM_CPUID4(int inputEcx)
{
uint32 output;
//NOT_TESTED();
__asm push ebx
__asm push ecx
__asm push edx
__asm mov eax, 4
__asm mov ecx, inputEcx
__asm _emit 0x0f __asm _emit 0xa2
__asm mov output, eax
__asm pop edx
__asm pop ecx
__asm pop ebx
return output;
}
#endif // VM_X86_64
#else // }
#error
#endif
#define CPUID_FOR_SIDE_EFFECTS() ((void)__GET_EAX_FROM_CPUID(0))
static INLINE void
__GET_CPUID4(int inputEcx, CPUIDRegs *regs)
{
__GET_CPUID2(4, inputEcx, regs);
}
/* The first parameter is used as an rvalue and then as an lvalue. */
#define GET_CPUID(_ax, _bx, _cx, _dx) { \
CPUIDRegs regs; \
__GET_CPUID(_ax, &regs); \
_ax = regs.eax; \
_bx = regs.ebx; \
_cx = regs.ecx; \
_dx = regs.edx; \
}
#endif

View File

@@ -0,0 +1,51 @@
/*********************************************************
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/*********************************************************
* The contents of this file are subject to the terms of the Common
* Development and Distribution License (the "License") version 1.0
* and no later version. You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.opensource.org/licenses/cddl1.php
*
* See the License for the specific language governing permissions
* and limitations under the License.
*
*********************************************************/
#ifndef _X86VENDOR_H_
#define _X86VENDOR_H_
/*
* CPU vendors
*/
typedef enum {
CPUID_VENDOR_UNKNOWN,
CPUID_VENDOR_COMMON,
CPUID_VENDOR_INTEL,
CPUID_VENDOR_AMD,
CPUID_VENDOR_CYRIX,
CPUID_VENDOR_VIA,
CPUID_NUM_VENDORS
} CpuidVendor;
#endif

View File

@@ -0,0 +1,57 @@
package message
import (
"errors"
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge"
)
var (
// ErrChannelOpen represents a failure to open a channel
ErrChannelOpen = errors.New("could not open channel")
// ErrChannelClose represents a failure to close a channel
ErrChannelClose = errors.New("could not close channel")
// ErrRpciSend represents a failure to send a message
ErrRpciSend = errors.New("unable to send RPCI command")
// ErrRpciReceive represents a failure to receive a message
ErrRpciReceive = errors.New("unable to receive RPCI command result")
)
// Channel is a communication channel between hypervisor and virtual machine
type Channel struct {
privChan bridge.MessageChannel
}
// NewChannel opens a new channel
func NewChannel(proto uint32) (*Channel, error) {
if channel := bridge.MessageOpen(proto); channel != nil {
return &Channel{
privChan: channel,
}, nil
}
return nil, ErrChannelOpen
}
// Close the channel
func (c *Channel) Close() error {
if status := bridge.MessageClose(bridge.MessageChannel(c.privChan)); status {
return nil
}
return ErrChannelClose
}
// Send a request
func (c *Channel) Send(request []byte) error {
if status := bridge.MessageSend(bridge.MessageChannel(c.privChan), request); status {
return nil
}
return ErrRpciSend
}
// Receive a response
func (c *Channel) Receive() ([]byte, error) {
if res, status := bridge.MessageReceive(bridge.MessageChannel(c.privChan)); status {
return res, nil
}
return nil, ErrRpciReceive
}

View File

@@ -0,0 +1,79 @@
package rpcout
import (
"errors"
"fmt"
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/message"
)
// ErrRpciFormat represents an invalid result format
var ErrRpciFormat = errors.New("invalid format for RPCI command result")
const rpciProtocolNum uint32 = 0x49435052
// SendOne is a command-oriented wrapper for SendOneRaw
func SendOne(format string, a ...interface{}) (reply []byte, ok bool, err error) {
request := fmt.Sprintf(format, a...)
return SendOneRaw([]byte(request))
}
// SendOneRaw uses a throw-away RPCOut to send a request
func SendOneRaw(request []byte) (reply []byte, ok bool, err error) {
out := &RPCOut{}
if err = out.Start(); err != nil {
return
}
if reply, ok, err = out.Send(request); err != nil {
return
}
if err = out.Stop(); err != nil {
return
}
return
}
// RPCOut is an ougoing connection from the VM to the hypervisor
type RPCOut struct {
channel *message.Channel
}
// Start opens the connection
func (out *RPCOut) Start() error {
channel, err := message.NewChannel(rpciProtocolNum)
if err != nil {
return err
}
out.channel = channel
return nil
}
// Stop closes the connection
func (out *RPCOut) Stop() error {
err := out.channel.Close()
out.channel = nil
return err
}
// Send emits a request and receives a response
func (out *RPCOut) Send(request []byte) (reply []byte, ok bool, err error) {
if err = out.channel.Send(request); err != nil {
return
}
var resp []byte
if resp, err = out.channel.Receive(); err != nil {
return
}
switch string(resp[:2]) {
case "0 ":
reply = resp[2:]
case "1 ":
reply = resp[2:]
ok = true
default:
err = ErrRpciFormat
}
return
}

View File

@@ -0,0 +1,57 @@
package rpcvmx
import (
"fmt"
"strconv"
"strings"
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/rpcout"
)
// Config gives access to the vmx config through the VMware backdoor
type Config struct{}
// NewConfig creates a new Config object
func NewConfig() *Config {
return &Config{}
}
// GetString returns the config string in the guestinfo.* namespace
func (c *Config) GetString(key string, defaultValue string) (string, error) {
out, ok, err := rpcout.SendOne("info-get guestinfo.%s", key)
if err != nil {
return "", err
} else if !ok {
return defaultValue, nil
}
return string(out), nil
}
// GetBool returns the config boolean in the guestinfo.* namespace
func (c *Config) GetBool(key string, defaultValue bool) (bool, error) {
val, err := c.GetString(key, fmt.Sprintf("%t", defaultValue))
if err != nil {
return false, err
}
switch strings.ToLower(val) {
case "true":
return true, nil
case "false":
return false, nil
default:
return defaultValue, nil
}
}
// GetInt returns the config integer in the guestinfo.* namespace
func (c *Config) GetInt(key string, defaultValue int) (int, error) {
val, err := c.GetString(key, "")
if err != nil {
return 0, err
}
res, err := strconv.Atoi(val)
if err != nil {
return defaultValue, nil
}
return res, nil
}

View File

@@ -0,0 +1,15 @@
package vmcheck
import (
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/sigma/vmw-guestinfo/bridge"
)
// IsVirtualWorld returns whether the code is running in a VMware virtual machine or no
func IsVirtualWorld() bool {
return bridge.VMCheckIsVirtualWorld()
}
// GetVersion returns the hypervisor version
func GetVersion() (version uint32, typ uint32) {
return bridge.VMCheckGetVersion()
}

View File

@@ -1,147 +0,0 @@
package yaml
import (
"math"
"strconv"
"strings"
)
// TODO: merge, timestamps, base 60 floats, omap.
type resolveMapItem struct {
value interface{}
tag string
}
var resolveTable = make([]byte, 256)
var resolveMap = make(map[string]resolveMapItem)
func init() {
t := resolveTable
t[int('+')] = 'S' // Sign
t[int('-')] = 'S'
for _, c := range "0123456789" {
t[int(c)] = 'D' // Digit
}
for _, c := range "yYnNtTfFoO~" {
t[int(c)] = 'M' // In map
}
t[int('.')] = '.' // Float (potentially in map)
var resolveMapList = []struct {
v interface{}
tag string
l []string
}{
{true, "!!bool", []string{"y", "Y", "yes", "Yes", "YES"}},
{true, "!!bool", []string{"true", "True", "TRUE"}},
{true, "!!bool", []string{"on", "On", "ON"}},
{false, "!!bool", []string{"n", "N", "no", "No", "NO"}},
{false, "!!bool", []string{"false", "False", "FALSE"}},
{false, "!!bool", []string{"off", "Off", "OFF"}},
{nil, "!!null", []string{"~", "null", "Null", "NULL"}},
{math.NaN(), "!!float", []string{".nan", ".NaN", ".NAN"}},
{math.Inf(+1), "!!float", []string{".inf", ".Inf", ".INF"}},
{math.Inf(+1), "!!float", []string{"+.inf", "+.Inf", "+.INF"}},
{math.Inf(-1), "!!float", []string{"-.inf", "-.Inf", "-.INF"}},
{"<<", "!!merge", []string{"<<"}},
}
m := resolveMap
for _, item := range resolveMapList {
for _, s := range item.l {
m[s] = resolveMapItem{item.v, item.tag}
}
}
}
const longTagPrefix = "tag:yaml.org,2002:"
func shortTag(tag string) string {
if strings.HasPrefix(tag, longTagPrefix) {
return "!!" + tag[len(longTagPrefix):]
}
return tag
}
func resolvableTag(tag string) bool {
switch tag {
case "", "!!str", "!!bool", "!!int", "!!float", "!!null":
return true
}
return false
}
func resolve(tag string, in string) (rtag string, out interface{}) {
tag = shortTag(tag)
if !resolvableTag(tag) {
return tag, in
}
defer func() {
if tag != "" && tag != rtag {
panic("Can't decode " + rtag + " '" + in + "' as a " + tag)
}
}()
if in == "" {
return "!!null", nil
}
c := resolveTable[in[0]]
if c == 0 {
// It's a string for sure. Nothing to do.
return "!!str", in
}
// Handle things we can lookup in a map.
if item, ok := resolveMap[in]; ok {
return item.tag, item.value
}
switch c {
case 'M':
// We've already checked the map above.
case '.':
// Not in the map, so maybe a normal float.
floatv, err := strconv.ParseFloat(in, 64)
if err == nil {
return "!!float", floatv
}
// XXX Handle base 60 floats here (WTF!)
case 'D', 'S':
// Int, float, or timestamp.
plain := strings.Replace(in, "_", "", -1)
intv, err := strconv.ParseInt(plain, 0, 64)
if err == nil {
if intv == int64(int(intv)) {
return "!!int", int(intv)
} else {
return "!!int", intv
}
}
floatv, err := strconv.ParseFloat(plain, 64)
if err == nil {
return "!!float", floatv
}
if strings.HasPrefix(plain, "0b") {
intv, err := strconv.ParseInt(plain[2:], 2, 64)
if err == nil {
return "!!int", int(intv)
}
} else if strings.HasPrefix(plain, "-0b") {
intv, err := strconv.ParseInt(plain[3:], 2, 64)
if err == nil {
return "!!int", -int(intv)
}
}
// XXX Handle timestamps here.
default:
panic("resolveTable item not yet handled: " +
string([]byte{c}) + " (with " + in + ")")
}
return "!!str", in
}

View File

@@ -77,3 +77,10 @@ coreos:
addr: 203.0.113.29:4001 addr: 203.0.113.29:4001
peer-addr: 192.0.2.13:7001 peer-addr: 192.0.2.13:7001
``` ```
## Bugs
Please use the [CoreOS issue tracker][bugs] to report all bugs, issues, and feature requests.
[bugs]: https://github.com/coreos/bugs/issues/new?labels=component/cloud-init

7
build
View File

@@ -1,7 +1,10 @@
#!/bin/bash -e #!/bin/bash -e
NAME="coreos-cloudinit"
ORG_PATH="github.com/coreos" ORG_PATH="github.com/coreos"
REPO_PATH="${ORG_PATH}/coreos-cloudinit" REPO_PATH="${ORG_PATH}/${NAME}"
VERSION=$(git describe --dirty --tags)
GLDFLAGS="-X main.version \"${VERSION}\""
if [ ! -h gopath/src/${REPO_PATH} ]; then if [ ! -h gopath/src/${REPO_PATH} ]; then
mkdir -p gopath/src/${ORG_PATH} mkdir -p gopath/src/${ORG_PATH}
@@ -11,4 +14,4 @@ fi
export GOBIN=${PWD}/bin export GOBIN=${PWD}/bin
export GOPATH=${PWD}/gopath export GOPATH=${PWD}/gopath
go build -o bin/coreos-cloudinit ${REPO_PATH} go build -ldflags "${GLDFLAGS}" -o ${GOBIN}/${NAME} ${REPO_PATH}

View File

@@ -1,28 +1,27 @@
/* // Copyright 2015 CoreOS, Inc.
Copyright 2014 CoreOS, Inc. //
// Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License. // You may obtain a copy of the License at
You may obtain a copy of the License at //
// http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0 //
// Unless required by applicable law or agreed to in writing, software
Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS,
distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and
See the License for the specific language governing permissions and // limitations under the License.
limitations under the License.
*/
package config package config
import ( import (
"fmt" "fmt"
"log"
"reflect" "reflect"
"regexp"
"strings" "strings"
"unicode"
"github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/gopkg.in/yaml.v1" "github.com/coreos/coreos-cloudinit/Godeps/_workspace/src/github.com/coreos/yaml"
) )
// CloudConfig encapsulates the entire cloud-config configuration file and maps // CloudConfig encapsulates the entire cloud-config configuration file and maps
@@ -30,33 +29,44 @@ import (
// used for internal use) have the YAML tag '-' so that they aren't marshalled. // used for internal use) have the YAML tag '-' so that they aren't marshalled.
type CloudConfig struct { type CloudConfig struct {
SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"` SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"`
Coreos struct { CoreOS CoreOS `yaml:"coreos"`
Etcd Etcd `yaml:"etcd"`
Fleet Fleet `yaml:"fleet"`
OEM OEM `yaml:"oem"`
Update Update `yaml:"update"`
Units []Unit `yaml:"units"`
} `yaml:"coreos"`
WriteFiles []File `yaml:"write_files"` WriteFiles []File `yaml:"write_files"`
Hostname string `yaml:"hostname"` Hostname string `yaml:"hostname"`
Users []User `yaml:"users"` Users []User `yaml:"users"`
ManageEtcHosts EtcHosts `yaml:"manage_etc_hosts"` ManageEtcHosts EtcHosts `yaml:"manage_etc_hosts"`
NetworkConfigPath string `yaml:"-"` }
NetworkConfig string `yaml:"-"`
type CoreOS struct {
Etcd Etcd `yaml:"etcd"`
Etcd2 Etcd2 `yaml:"etcd2"`
Flannel Flannel `yaml:"flannel"`
Fleet Fleet `yaml:"fleet"`
Locksmith Locksmith `yaml:"locksmith"`
OEM OEM `yaml:"oem"`
Update Update `yaml:"update"`
Units []Unit `yaml:"units"`
}
func IsCloudConfig(userdata string) bool {
header := strings.SplitN(userdata, "\n", 2)[0]
// Trim trailing whitespaces
header = strings.TrimRightFunc(header, unicode.IsSpace)
return (header == "#cloud-config")
} }
// NewCloudConfig instantiates a new CloudConfig from the given contents (a // NewCloudConfig instantiates a new CloudConfig from the given contents (a
// string of YAML), returning any error encountered. It will ignore unknown // string of YAML), returning any error encountered. It will ignore unknown
// fields but log encountering them. // fields but log encountering them.
func NewCloudConfig(contents string) (*CloudConfig, error) { func NewCloudConfig(contents string) (*CloudConfig, error) {
yaml.UnmarshalMappingKeyTransform = func(nameIn string) (nameOut string) {
return strings.Replace(nameIn, "-", "_", -1)
}
var cfg CloudConfig var cfg CloudConfig
err := yaml.Unmarshal([]byte(contents), &cfg) err := yaml.Unmarshal([]byte(contents), &cfg)
if err != nil {
return &cfg, err return &cfg, err
} }
warnOnUnrecognizedKeys(contents, log.Printf)
return &cfg, nil
}
func (cc CloudConfig) String() string { func (cc CloudConfig) String() string {
bytes, err := yaml.Marshal(cc) bytes, err := yaml.Marshal(cc)
@@ -76,10 +86,20 @@ func IsZero(c interface{}) bool {
return isZero(reflect.ValueOf(c)) return isZero(reflect.ValueOf(c))
} }
// AssertValid checks the fields in the structure and makes sure that they type ErrorValid struct {
// contain valid values as specified by the 'valid' flag. Empty fields are Value string
Valid string
Field string
}
func (e ErrorValid) Error() string {
return fmt.Sprintf("invalid value %q for option %q (valid options: %q)", e.Value, e.Field, e.Valid)
}
// AssertStructValid checks the fields in the structure and makes sure that
// they contain valid values as specified by the 'valid' flag. Empty fields are
// implicitly valid. // implicitly valid.
func AssertValid(c interface{}) error { func AssertStructValid(c interface{}) error {
ct := reflect.TypeOf(c) ct := reflect.TypeOf(c)
cv := reflect.ValueOf(c) cv := reflect.ValueOf(c)
for i := 0; i < ct.NumField(); i++ { for i := 0; i < ct.NumField(); i++ {
@@ -88,15 +108,32 @@ func AssertValid(c interface{}) error {
continue continue
} }
valid := ft.Tag.Get("valid") if err := AssertValid(cv.Field(i), ft.Tag.Get("valid")); err != nil {
val := cv.Field(i) err.Field = ft.Name
if !isValid(val, valid) { return err
return fmt.Errorf("invalid value \"%v\" for option %q (valid options: %q)", val.Interface(), ft.Name, valid)
} }
} }
return nil return nil
} }
// AssertValid checks to make sure that the given value is in the list of
// valid values. Zero values are implicitly valid.
func AssertValid(value reflect.Value, valid string) *ErrorValid {
if valid == "" || isZero(value) {
return nil
}
vs := fmt.Sprintf("%v", value.Interface())
if m, _ := regexp.MatchString(valid, vs); m {
return nil
}
return &ErrorValid{
Value: vs,
Valid: valid,
}
}
func isZero(v reflect.Value) bool { func isZero(v reflect.Value) bool {
switch v.Kind() { switch v.Kind() {
case reflect.Struct: case reflect.Struct:
@@ -115,100 +152,3 @@ func isZero(v reflect.Value) bool {
func isFieldExported(f reflect.StructField) bool { func isFieldExported(f reflect.StructField) bool {
return f.PkgPath == "" return f.PkgPath == ""
} }
func isValid(v reflect.Value, valid string) bool {
if valid == "" || isZero(v) {
return true
}
vs := fmt.Sprintf("%v", v.Interface())
for _, valid := range strings.Split(valid, ",") {
if vs == valid {
return true
}
}
return false
}
type warner func(format string, v ...interface{})
// warnOnUnrecognizedKeys parses the contents of a cloud-config file and calls
// warn(msg, key) for every unrecognized key (i.e. those not present in CloudConfig)
func warnOnUnrecognizedKeys(contents string, warn warner) {
// Generate a map of all understood cloud config options
var cc map[string]interface{}
b, _ := yaml.Marshal(&CloudConfig{})
yaml.Unmarshal(b, &cc)
// Now unmarshal the entire provided contents
var c map[string]interface{}
yaml.Unmarshal([]byte(contents), &c)
// Check that every key in the contents exists in the cloud config
for k, _ := range c {
if _, ok := cc[k]; !ok {
warn("Warning: unrecognized key %q in provided cloud config - ignoring section", k)
}
}
// Check for unrecognized coreos options, if any are set
if coreos, ok := c["coreos"]; ok {
if set, ok := coreos.(map[interface{}]interface{}); ok {
known := cc["coreos"].(map[interface{}]interface{})
for k, _ := range set {
if key, ok := k.(string); ok {
if _, ok := known[key]; !ok {
warn("Warning: unrecognized key %q in coreos section of provided cloud config - ignoring", key)
}
} else {
warn("Warning: unrecognized key %q in coreos section of provided cloud config - ignoring", k)
}
}
}
}
// Check for any badly-specified users, if any are set
if users, ok := c["users"]; ok {
var known map[string]interface{}
b, _ := yaml.Marshal(&User{})
yaml.Unmarshal(b, &known)
if set, ok := users.([]interface{}); ok {
for _, u := range set {
if user, ok := u.(map[interface{}]interface{}); ok {
for k, _ := range user {
if key, ok := k.(string); ok {
if _, ok := known[key]; !ok {
warn("Warning: unrecognized key %q in user section of cloud config - ignoring", key)
}
} else {
warn("Warning: unrecognized key %q in user section of cloud config - ignoring", k)
}
}
}
}
}
}
// Check for any badly-specified files, if any are set
if files, ok := c["write_files"]; ok {
var known map[string]interface{}
b, _ := yaml.Marshal(&File{})
yaml.Unmarshal(b, &known)
if set, ok := files.([]interface{}); ok {
for _, f := range set {
if file, ok := f.(map[interface{}]interface{}); ok {
for k, _ := range file {
if key, ok := k.(string); ok {
if _, ok := known[key]; !ok {
warn("Warning: unrecognized key %q in file section of cloud config - ignoring", key)
}
} else {
warn("Warning: unrecognized key %q in file section of cloud config - ignoring", k)
}
}
}
}
}
}
}

View File

@@ -1,32 +1,82 @@
/* // Copyright 2015 CoreOS, Inc.
Copyright 2014 CoreOS, Inc. //
// Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License. // You may obtain a copy of the License at
You may obtain a copy of the License at //
// http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0 //
// Unless required by applicable law or agreed to in writing, software
Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS,
distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and
See the License for the specific language governing permissions and // limitations under the License.
limitations under the License.
*/
package config package config
import ( import (
"errors"
"fmt"
"reflect" "reflect"
"regexp"
"strings" "strings"
"testing" "testing"
) )
func TestNewCloudConfig(t *testing.T) {
tests := []struct {
contents string
config CloudConfig
}{
{},
{
contents: "#cloud-config\nwrite_files:\n - path: underscore",
config: CloudConfig{WriteFiles: []File{File{Path: "underscore"}}},
},
{
contents: "#cloud-config\nwrite-files:\n - path: hyphen",
config: CloudConfig{WriteFiles: []File{File{Path: "hyphen"}}},
},
{
contents: "#cloud-config\ncoreos:\n update:\n reboot-strategy: off",
config: CloudConfig{CoreOS: CoreOS{Update: Update{RebootStrategy: "off"}}},
},
{
contents: "#cloud-config\ncoreos:\n update:\n reboot-strategy: false",
config: CloudConfig{CoreOS: CoreOS{Update: Update{RebootStrategy: "false"}}},
},
{
contents: "#cloud-config\nwrite_files:\n - permissions: 0744",
config: CloudConfig{WriteFiles: []File{File{RawFilePermissions: "0744"}}},
},
{
contents: "#cloud-config\nwrite_files:\n - permissions: 744",
config: CloudConfig{WriteFiles: []File{File{RawFilePermissions: "744"}}},
},
{
contents: "#cloud-config\nwrite_files:\n - permissions: '0744'",
config: CloudConfig{WriteFiles: []File{File{RawFilePermissions: "0744"}}},
},
{
contents: "#cloud-config\nwrite_files:\n - permissions: '744'",
config: CloudConfig{WriteFiles: []File{File{RawFilePermissions: "744"}}},
},
}
for i, tt := range tests {
config, err := NewCloudConfig(tt.contents)
if err != nil {
t.Errorf("bad error (test case #%d): want %v, got %s", i, nil, err)
}
if !reflect.DeepEqual(&tt.config, config) {
t.Errorf("bad config (test case #%d): want %#v, got %#v", i, tt.config, config)
}
}
}
func TestIsZero(t *testing.T) { func TestIsZero(t *testing.T) {
for _, tt := range []struct { tests := []struct {
c interface{} c interface{}
empty bool empty bool
}{ }{
{struct{}{}, true}, {struct{}{}, true},
@@ -36,74 +86,78 @@ func TestIsZero(t *testing.T) {
{struct{ A string }{A: "hello"}, false}, {struct{ A string }{A: "hello"}, false},
{struct{ A int }{}, true}, {struct{ A int }{}, true},
{struct{ A int }{A: 1}, false}, {struct{ A int }{A: 1}, false},
} { }
for _, tt := range tests {
if empty := IsZero(tt.c); tt.empty != empty { if empty := IsZero(tt.c); tt.empty != empty {
t.Errorf("bad result (%q): want %t, got %t", tt.c, tt.empty, empty) t.Errorf("bad result (%q): want %t, got %t", tt.c, tt.empty, empty)
} }
} }
} }
func TestAssertValid(t *testing.T) { func TestAssertStructValid(t *testing.T) {
for _, tt := range []struct { tests := []struct {
c interface{} c interface{}
err error err error
}{ }{
{struct{}{}, nil}, {struct{}{}, nil},
{struct { {struct {
A, b string `valid:"1,2"` A, b string `valid:"^1|2$"`
}{}, nil}, }{}, nil},
{struct { {struct {
A, b string `valid:"1,2"` A, b string `valid:"^1|2$"`
}{A: "1", b: "2"}, nil}, }{A: "1", b: "2"}, nil},
{struct { {struct {
A, b string `valid:"1,2"` A, b string `valid:"^1|2$"`
}{A: "1", b: "hello"}, nil}, }{A: "1", b: "hello"}, nil},
{struct { {struct {
A, b string `valid:"1,2"` A, b string `valid:"^1|2$"`
}{A: "hello", b: "2"}, errors.New("invalid value \"hello\" for option \"A\" (valid options: \"1,2\")")}, }{A: "hello", b: "2"}, &ErrorValid{Value: "hello", Field: "A", Valid: "^1|2$"}},
{struct { {struct {
A, b int `valid:"1,2"` A, b int `valid:"^1|2$"`
}{}, nil}, }{}, nil},
{struct { {struct {
A, b int `valid:"1,2"` A, b int `valid:"^1|2$"`
}{A: 1, b: 2}, nil}, }{A: 1, b: 2}, nil},
{struct { {struct {
A, b int `valid:"1,2"` A, b int `valid:"^1|2$"`
}{A: 1, b: 9}, nil}, }{A: 1, b: 9}, nil},
{struct { {struct {
A, b int `valid:"1,2"` A, b int `valid:"^1|2$"`
}{A: 9, b: 2}, errors.New("invalid value \"9\" for option \"A\" (valid options: \"1,2\")")}, }{A: 9, b: 2}, &ErrorValid{Value: "9", Field: "A", Valid: "^1|2$"}},
} { }
if err := AssertValid(tt.c); !reflect.DeepEqual(tt.err, err) {
for _, tt := range tests {
if err := AssertStructValid(tt.c); !reflect.DeepEqual(tt.err, err) {
t.Errorf("bad result (%q): want %q, got %q", tt.c, tt.err, err) t.Errorf("bad result (%q): want %q, got %q", tt.c, tt.err, err)
} }
} }
} }
func TestCloudConfigInvalidKeys(t *testing.T) { func TestConfigCompile(t *testing.T) {
defer func() { tests := []interface{}{
if r := recover(); r != nil { Etcd{},
t.Fatalf("panic while instantiating CloudConfig with nil keys: %v", r) File{},
Flannel{},
Fleet{},
Locksmith{},
OEM{},
Unit{},
Update{},
} }
}()
for _, tt := range []struct { for _, tt := range tests {
contents string ttt := reflect.TypeOf(tt)
}{ for i := 0; i < ttt.NumField(); i++ {
{"coreos:"}, ft := ttt.Field(i)
{"ssh_authorized_keys:"}, if !isFieldExported(ft) {
{"ssh_authorized_keys:\n -"}, continue
{"ssh_authorized_keys:\n - 0:"}, }
{"write_files:"},
{"write_files:\n -"}, if _, err := regexp.Compile(ft.Tag.Get("valid")); err != nil {
{"write_files:\n - 0:"}, t.Errorf("bad regexp(%s.%s): want %v, got %s", ttt.Name(), ft.Name, nil, err)
{"users:"}, }
{"users:\n -"},
{"users:\n - 0:"},
} {
_, err := NewCloudConfig(tt.contents)
if err != nil {
t.Fatalf("error instantiating CloudConfig with invalid keys: %v", err)
} }
} }
} }
@@ -138,7 +192,7 @@ hostname:
if cfg.Hostname != "foo" { if cfg.Hostname != "foo" {
t.Fatalf("hostname not correctly set when invalid keys are present") t.Fatalf("hostname not correctly set when invalid keys are present")
} }
if cfg.Coreos.Etcd.Discovery != "https://discovery.etcd.io/827c73219eeb2fa5530027c37bf18877" { if cfg.CoreOS.Etcd.Discovery != "https://discovery.etcd.io/827c73219eeb2fa5530027c37bf18877" {
t.Fatalf("etcd section not correctly set when invalid keys are present") t.Fatalf("etcd section not correctly set when invalid keys are present")
} }
if len(cfg.WriteFiles) < 1 || cfg.WriteFiles[0].Content != "fun" || cfg.WriteFiles[0].Path != "/var/party" { if len(cfg.WriteFiles) < 1 || cfg.WriteFiles[0].Content != "fun" || cfg.WriteFiles[0].Path != "/var/party" {
@@ -147,29 +201,6 @@ hostname:
if len(cfg.Users) < 1 || cfg.Users[0].Name != "fry" || cfg.Users[0].PasswordHash != "somehash" { if len(cfg.Users) < 1 || cfg.Users[0].Name != "fry" || cfg.Users[0].PasswordHash != "somehash" {
t.Fatalf("users section not correctly set when invalid keys are present") t.Fatalf("users section not correctly set when invalid keys are present")
} }
var warnings string
catchWarn := func(f string, v ...interface{}) {
warnings += fmt.Sprintf(f, v...)
}
warnOnUnrecognizedKeys(contents, catchWarn)
if !strings.Contains(warnings, "coreos_unknown") {
t.Errorf("warnings did not catch unrecognized coreos option coreos_unknown")
}
if !strings.Contains(warnings, "bare_unknown") {
t.Errorf("warnings did not catch unrecognized key bare_unknown")
}
if !strings.Contains(warnings, "section_unknown") {
t.Errorf("warnings did not catch unrecognized key section_unknown")
}
if !strings.Contains(warnings, "user_unknown") {
t.Errorf("warnings did not catch unrecognized user key user_unknown")
}
if !strings.Contains(warnings, "file_unknown") {
t.Errorf("warnings did not catch unrecognized file key file_unknown")
}
} }
// Assert that the parsing of a cloud config file "generally works" // Assert that the parsing of a cloud config file "generally works"
@@ -200,7 +231,7 @@ coreos:
etcd: etcd:
discovery: "https://discovery.etcd.io/827c73219eeb2fa5530027c37bf18877" discovery: "https://discovery.etcd.io/827c73219eeb2fa5530027c37bf18877"
update: update:
reboot-strategy: reboot reboot_strategy: reboot
units: units:
- name: 50-eth0.network - name: 50-eth0.network
runtime: yes runtime: yes
@@ -217,9 +248,9 @@ coreos:
oem: oem:
id: rackspace id: rackspace
name: Rackspace Cloud Servers name: Rackspace Cloud Servers
version-id: 168.0.0 version_id: 168.0.0
home-url: https://www.rackspace.com/cloud/servers/ home_url: https://www.rackspace.com/cloud/servers/
bug-report-url: https://github.com/coreos/coreos-overlay bug_report_url: https://github.com/coreos/coreos-overlay
ssh_authorized_keys: ssh_authorized_keys:
- foobar - foobar
- foobaz - foobaz
@@ -267,10 +298,10 @@ hostname: trontastic
} }
} }
if len(cfg.Coreos.Units) != 1 { if len(cfg.CoreOS.Units) != 1 {
t.Error("Failed to parse correct number of units") t.Error("Failed to parse correct number of units")
} else { } else {
u := cfg.Coreos.Units[0] u := cfg.CoreOS.Units[0]
expect := `[Match] expect := `[Match]
Name=eth47 Name=eth47
@@ -286,19 +317,16 @@ Address=10.209.171.177/19
if u.Name != "50-eth0.network" { if u.Name != "50-eth0.network" {
t.Errorf("Unit has incorrect name %s", u.Name) t.Errorf("Unit has incorrect name %s", u.Name)
} }
if u.Type() != "network" {
t.Errorf("Unit has incorrect type '%s'", u.Type())
}
} }
if cfg.Coreos.OEM.ID != "rackspace" { if cfg.CoreOS.OEM.ID != "rackspace" {
t.Errorf("Failed parsing coreos.oem. Expected ID 'rackspace', got %q.", cfg.Coreos.OEM.ID) t.Errorf("Failed parsing coreos.oem. Expected ID 'rackspace', got %q.", cfg.CoreOS.OEM.ID)
} }
if cfg.Hostname != "trontastic" { if cfg.Hostname != "trontastic" {
t.Errorf("Failed to parse hostname") t.Errorf("Failed to parse hostname")
} }
if cfg.Coreos.Update.RebootStrategy != "reboot" { if cfg.CoreOS.Update.RebootStrategy != "reboot" {
t.Errorf("Failed to parse locksmith strategy") t.Errorf("Failed to parse locksmith strategy")
} }
} }
@@ -329,43 +357,25 @@ func TestCloudConfigSerializationHeader(t *testing.T) {
} }
} }
// TestDropInIgnored asserts that users are unable to set DropIn=True on units
func TestDropInIgnored(t *testing.T) {
contents := `
coreos:
units:
- name: test
dropin: true
`
cfg, err := NewCloudConfig(contents)
if err != nil || len(cfg.Coreos.Units) != 1 {
t.Fatalf("Encountered unexpected error: %v", err)
}
if len(cfg.Coreos.Units) != 1 || cfg.Coreos.Units[0].Name != "test" {
t.Fatalf("Expected 1 unit, but got %d: %v", len(cfg.Coreos.Units), cfg.Coreos.Units)
}
if cfg.Coreos.Units[0].DropIn {
t.Errorf("dropin option on unit in cloud-config was not ignored!")
}
}
func TestCloudConfigUsers(t *testing.T) { func TestCloudConfigUsers(t *testing.T) {
contents := ` contents := `
users: users:
- name: elroy - name: elroy
passwd: somehash passwd: somehash
ssh-authorized-keys: ssh_authorized_keys:
- somekey - somekey
gecos: arbitrary comment gecos: arbitrary comment
homedir: /home/place homedir: /home/place
no-create-home: yes no_create_home: yes
primary-group: things lock_passwd: false
primary_group: things
groups: groups:
- ping - ping
- pong - pong
no-user-group: true no_user_group: true
system: y system: y
no-log-init: True no_log_init: True
shell: /bin/sh
` `
cfg, err := NewCloudConfig(contents) cfg, err := NewCloudConfig(contents)
if err != nil { if err != nil {
@@ -404,11 +414,11 @@ users:
} }
if !user.NoCreateHome { if !user.NoCreateHome {
t.Errorf("Failed to parse no-create-home field") t.Errorf("Failed to parse no_create_home field")
} }
if user.PrimaryGroup != "things" { if user.PrimaryGroup != "things" {
t.Errorf("Failed to parse primary-group field, got %q", user.PrimaryGroup) t.Errorf("Failed to parse primary_group field, got %q", user.PrimaryGroup)
} }
if len(user.Groups) != 2 { if len(user.Groups) != 2 {
@@ -423,7 +433,7 @@ users:
} }
if !user.NoUserGroup { if !user.NoUserGroup {
t.Errorf("Failed to parse no-user-group field") t.Errorf("Failed to parse no_user_group field")
} }
if !user.System { if !user.System {
@@ -431,7 +441,11 @@ users:
} }
if !user.NoLogInit { if !user.NoLogInit {
t.Errorf("Failed to parse no-log-init field") t.Errorf("Failed to parse no_log_init field")
}
if user.Shell != "/bin/sh" {
t.Errorf("Failed to parse shell field, got %q", user.Shell)
} }
} }
@@ -440,7 +454,7 @@ func TestCloudConfigUsersGithubUser(t *testing.T) {
contents := ` contents := `
users: users:
- name: elroy - name: elroy
coreos-ssh-import-github: bcwaldon coreos_ssh_import_github: bcwaldon
` `
cfg, err := NewCloudConfig(contents) cfg, err := NewCloudConfig(contents)
if err != nil { if err != nil {
@@ -466,7 +480,7 @@ func TestCloudConfigUsersSSHImportURL(t *testing.T) {
contents := ` contents := `
users: users:
- name: elroy - name: elroy
coreos-ssh-import-url: https://token:x-auth-token@github.enterprise.com/api/v3/polvi/keys coreos_ssh_import_url: https://token:x-auth-token@github.enterprise.com/api/v3/polvi/keys
` `
cfg, err := NewCloudConfig(contents) cfg, err := NewCloudConfig(contents)
if err != nil { if err != nil {

56
config/decode.go Normal file
View File

@@ -0,0 +1,56 @@
package config
import (
"bytes"
"compress/gzip"
"encoding/base64"
"fmt"
)
func DecodeBase64Content(content string) ([]byte, error) {
output, err := base64.StdEncoding.DecodeString(content)
if err != nil {
return nil, fmt.Errorf("Unable to decode base64: %q", err)
}
return output, nil
}
func DecodeGzipContent(content string) ([]byte, error) {
gzr, err := gzip.NewReader(bytes.NewReader([]byte(content)))
if err != nil {
return nil, fmt.Errorf("Unable to decode gzip: %q", err)
}
defer gzr.Close()
buf := new(bytes.Buffer)
buf.ReadFrom(gzr)
return buf.Bytes(), nil
}
func DecodeContent(content string, encoding string) ([]byte, error) {
switch encoding {
case "":
return []byte(content), nil
case "b64", "base64":
return DecodeBase64Content(content)
case "gz", "gzip":
return DecodeGzipContent(content)
case "gz+base64", "gzip+base64", "gz+b64", "gzip+b64":
gz, err := DecodeBase64Content(content)
if err != nil {
return nil, err
}
return DecodeGzipContent(string(gz))
}
return nil, fmt.Errorf("Unsupported encoding %q", encoding)
}

View File

@@ -1,18 +1,16 @@
/* // Copyright 2015 CoreOS, Inc.
Copyright 2014 CoreOS, Inc. //
// Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License. // You may obtain a copy of the License at
You may obtain a copy of the License at //
// http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0 //
// Unless required by applicable law or agreed to in writing, software
Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS,
distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and
See the License for the specific language governing permissions and // limitations under the License.
limitations under the License.
*/
package config package config

View File

@@ -1,48 +1,67 @@
/* // Copyright 2015 CoreOS, Inc.
Copyright 2014 CoreOS, Inc. //
// Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License. // You may obtain a copy of the License at
You may obtain a copy of the License at //
// http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0 //
// Unless required by applicable law or agreed to in writing, software
Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS,
distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and
See the License for the specific language governing permissions and // limitations under the License.
limitations under the License.
*/
package config package config
type Etcd struct { type Etcd struct {
Addr string `yaml:"addr" env:"ETCD_ADDR"` Addr string `yaml:"addr" env:"ETCD_ADDR"`
BindAddr string `yaml:"bind-addr" env:"ETCD_BIND_ADDR"` AdvertiseClientURLs string `yaml:"advertise_client_urls" env:"ETCD_ADVERTISE_CLIENT_URLS" deprecated:"etcd2 options no longer work for etcd"`
CAFile string `yaml:"ca-file" env:"ETCD_CA_FILE"` BindAddr string `yaml:"bind_addr" env:"ETCD_BIND_ADDR"`
CertFile string `yaml:"cert-file" env:"ETCD_CERT_FILE"` CAFile string `yaml:"ca_file" env:"ETCD_CA_FILE"`
ClusterActiveSize string `yaml:"cluster-active-size" env:"ETCD_CLUSTER_ACTIVE_SIZE"` CertFile string `yaml:"cert_file" env:"ETCD_CERT_FILE"`
ClusterRemoveDelay string `yaml:"cluster-remove-delay" env:"ETCD_CLUSTER_REMOVE_DELAY"` ClusterActiveSize int `yaml:"cluster_active_size" env:"ETCD_CLUSTER_ACTIVE_SIZE"`
ClusterSyncInterval string `yaml:"cluster-sync-interval" env:"ETCD_CLUSTER_SYNC_INTERVAL"` ClusterRemoveDelay float64 `yaml:"cluster_remove_delay" env:"ETCD_CLUSTER_REMOVE_DELAY"`
Cors string `yaml:"cors" env:"ETCD_CORS"` ClusterSyncInterval float64 `yaml:"cluster_sync_interval" env:"ETCD_CLUSTER_SYNC_INTERVAL"`
CPUProfileFile string `yaml:"cpu-profile-file" env:"ETCD_CPU_PROFILE_FILE"` CorsOrigins string `yaml:"cors" env:"ETCD_CORS"`
DataDir string `yaml:"data-dir" env:"ETCD_DATA_DIR"` DataDir string `yaml:"data_dir" env:"ETCD_DATA_DIR"`
Discovery string `yaml:"discovery" env:"ETCD_DISCOVERY"` Discovery string `yaml:"discovery" env:"ETCD_DISCOVERY"`
HTTPReadTimeout string `yaml:"http-read-timeout" env:"ETCD_HTTP_READ_TIMEOUT"` DiscoveryFallback string `yaml:"discovery_fallback" env:"ETCD_DISCOVERY_FALLBACK" deprecated:"etcd2 options no longer work for etcd"`
HTTPWriteTimeout string `yaml:"http-write-timeout" env:"ETCD_HTTP_WRITE_TIMEOUT"` DiscoverySRV string `yaml:"discovery_srv" env:"ETCD_DISCOVERY_SRV" deprecated:"etcd2 options no longer work for etcd"`
KeyFile string `yaml:"key-file" env:"ETCD_KEY_FILE"` DiscoveryProxy string `yaml:"discovery_proxy" env:"ETCD_DISCOVERY_PROXY" deprecated:"etcd2 options no longer work for etcd"`
MaxClusterSize string `yaml:"max-cluster-size" env:"ETCD_MAX_CLUSTER_SIZE"` ElectionTimeout int `yaml:"election_timeout" env:"ETCD_ELECTION_TIMEOUT" deprecated:"etcd2 options no longer work for etcd"`
MaxResultBuffer string `yaml:"max-result-buffer" env:"ETCD_MAX_RESULT_BUFFER"` ForceNewCluster bool `yaml:"force_new_cluster" env:"ETCD_FORCE_NEW_CLUSTER" deprecated:"etcd2 options no longer work for etcd"`
MaxRetryAttempts string `yaml:"max-retry-attempts" env:"ETCD_MAX_RETRY_ATTEMPTS"` GraphiteHost string `yaml:"graphite_host" env:"ETCD_GRAPHITE_HOST"`
HeartbeatInterval int `yaml:"heartbeat_interval" env:"ETCD_HEARTBEAT_INTERVAL" deprecated:"etcd2 options no longer work for etcd"`
HTTPReadTimeout float64 `yaml:"http_read_timeout" env:"ETCD_HTTP_READ_TIMEOUT"`
HTTPWriteTimeout float64 `yaml:"http_write_timeout" env:"ETCD_HTTP_WRITE_TIMEOUT"`
InitialAdvertisePeerURLs string `yaml:"initial_advertise_peer_urls" env:"ETCD_INITIAL_ADVERTISE_PEER_URLS" deprecated:"etcd2 options no longer work for etcd"`
InitialCluster string `yaml:"initial_cluster" env:"ETCD_INITIAL_CLUSTER" deprecated:"etcd2 options no longer work for etcd"`
InitialClusterState string `yaml:"initial_cluster_state" env:"ETCD_INITIAL_CLUSTER_STATE" deprecated:"etcd2 options no longer work for etcd"`
InitialClusterToken string `yaml:"initial_cluster_token" env:"ETCD_INITIAL_CLUSTER_TOKEN" deprecated:"etcd2 options no longer work for etcd"`
KeyFile string `yaml:"key_file" env:"ETCD_KEY_FILE"`
ListenClientURLs string `yaml:"listen_client_urls" env:"ETCD_LISTEN_CLIENT_URLS" deprecated:"etcd2 options no longer work for etcd"`
ListenPeerURLs string `yaml:"listen_peer_urls" env:"ETCD_LISTEN_PEER_URLS" deprecated:"etcd2 options no longer work for etcd"`
MaxResultBuffer int `yaml:"max_result_buffer" env:"ETCD_MAX_RESULT_BUFFER"`
MaxRetryAttempts int `yaml:"max_retry_attempts" env:"ETCD_MAX_RETRY_ATTEMPTS"`
MaxSnapshots int `yaml:"max_snapshots" env:"ETCD_MAX_SNAPSHOTS" deprecated:"etcd2 options no longer work for etcd"`
MaxWALs int `yaml:"max_wals" env:"ETCD_MAX_WALS" deprecated:"etcd2 options no longer work for etcd"`
Name string `yaml:"name" env:"ETCD_NAME"` Name string `yaml:"name" env:"ETCD_NAME"`
PeerAddr string `yaml:"peer-addr" env:"ETCD_PEER_ADDR"` PeerAddr string `yaml:"peer_addr" env:"ETCD_PEER_ADDR"`
PeerBindAddr string `yaml:"peer-bind-addr" env:"ETCD_PEER_BIND_ADDR"` PeerBindAddr string `yaml:"peer_bind_addr" env:"ETCD_PEER_BIND_ADDR"`
PeerCAFile string `yaml:"peer-ca-file" env:"ETCD_PEER_CA_FILE"` PeerCAFile string `yaml:"peer_ca_file" env:"ETCD_PEER_CA_FILE"`
PeerCertFile string `yaml:"peer-cert-file" env:"ETCD_PEER_CERT_FILE"` PeerCertFile string `yaml:"peer_cert_file" env:"ETCD_PEER_CERT_FILE"`
PeerKeyFile string `yaml:"peer-key-file" env:"ETCD_PEER_KEY_FILE"` PeerElectionTimeout int `yaml:"peer_election_timeout" env:"ETCD_PEER_ELECTION_TIMEOUT"`
PeerHeartbeatInterval int `yaml:"peer_heartbeat_interval" env:"ETCD_PEER_HEARTBEAT_INTERVAL"`
PeerKeyFile string `yaml:"peer_key_file" env:"ETCD_PEER_KEY_FILE"`
Peers string `yaml:"peers" env:"ETCD_PEERS"` Peers string `yaml:"peers" env:"ETCD_PEERS"`
PeersFile string `yaml:"peers-file" env:"ETCD_PEERS_FILE"` PeersFile string `yaml:"peers_file" env:"ETCD_PEERS_FILE"`
Snapshot string `yaml:"snapshot" env:"ETCD_SNAPSHOT"` Proxy string `yaml:"proxy" env:"ETCD_PROXY" deprecated:"etcd2 options no longer work for etcd"`
Verbose string `yaml:"verbose" env:"ETCD_VERBOSE"` RetryInterval float64 `yaml:"retry_interval" env:"ETCD_RETRY_INTERVAL"`
VeryVerbose string `yaml:"very-verbose" env:"ETCD_VERY_VERBOSE"` Snapshot bool `yaml:"snapshot" env:"ETCD_SNAPSHOT"`
SnapshotCount int `yaml:"snapshot_count" env:"ETCD_SNAPSHOTCOUNT"`
StrTrace string `yaml:"trace" env:"ETCD_TRACE"`
Verbose bool `yaml:"verbose" env:"ETCD_VERBOSE"`
VeryVerbose bool `yaml:"very_verbose" env:"ETCD_VERY_VERBOSE"`
VeryVeryVerbose bool `yaml:"very_very_verbose" env:"ETCD_VERY_VERY_VERBOSE"`
} }

57
config/etcd2.go Normal file
View File

@@ -0,0 +1,57 @@
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
type Etcd2 struct {
AdvertiseClientURLs string `yaml:"advertise_client_urls" env:"ETCD_ADVERTISE_CLIENT_URLS"`
CAFile string `yaml:"ca_file" env:"ETCD_CA_FILE" deprecated:"ca_file obsoleted by trusted_ca_file and client_cert_auth"`
CertFile string `yaml:"cert_file" env:"ETCD_CERT_FILE"`
ClientCertAuth bool `yaml:"client_cert_auth" env:"ETCD_CLIENT_CERT_AUTH"`
CorsOrigins string `yaml:"cors" env:"ETCD_CORS"`
DataDir string `yaml:"data_dir" env:"ETCD_DATA_DIR"`
Debug bool `yaml:"debug" env:"ETCD_DEBUG"`
Discovery string `yaml:"discovery" env:"ETCD_DISCOVERY"`
DiscoveryFallback string `yaml:"discovery_fallback" env:"ETCD_DISCOVERY_FALLBACK"`
DiscoverySRV string `yaml:"discovery_srv" env:"ETCD_DISCOVERY_SRV"`
DiscoveryProxy string `yaml:"discovery_proxy" env:"ETCD_DISCOVERY_PROXY"`
ElectionTimeout int `yaml:"election_timeout" env:"ETCD_ELECTION_TIMEOUT"`
ForceNewCluster bool `yaml:"force_new_cluster" env:"ETCD_FORCE_NEW_CLUSTER"`
HeartbeatInterval int `yaml:"heartbeat_interval" env:"ETCD_HEARTBEAT_INTERVAL"`
InitialAdvertisePeerURLs string `yaml:"initial_advertise_peer_urls" env:"ETCD_INITIAL_ADVERTISE_PEER_URLS"`
InitialCluster string `yaml:"initial_cluster" env:"ETCD_INITIAL_CLUSTER"`
InitialClusterState string `yaml:"initial_cluster_state" env:"ETCD_INITIAL_CLUSTER_STATE"`
InitialClusterToken string `yaml:"initial_cluster_token" env:"ETCD_INITIAL_CLUSTER_TOKEN"`
KeyFile string `yaml:"key_file" env:"ETCD_KEY_FILE"`
ListenClientURLs string `yaml:"listen_client_urls" env:"ETCD_LISTEN_CLIENT_URLS"`
ListenPeerURLs string `yaml:"listen_peer_urls" env:"ETCD_LISTEN_PEER_URLS"`
LogPackageLevels string `yaml:"log_package_levels" env:"ETCD_LOG_PACKAGE_LEVELS"`
MaxSnapshots int `yaml:"max_snapshots" env:"ETCD_MAX_SNAPSHOTS"`
MaxWALs int `yaml:"max_wals" env:"ETCD_MAX_WALS"`
Name string `yaml:"name" env:"ETCD_NAME"`
PeerCAFile string `yaml:"peer_ca_file" env:"ETCD_PEER_CA_FILE" deprecated:"peer_ca_file obsoleted peer_trusted_ca_file and peer_client_cert_auth"`
PeerCertFile string `yaml:"peer_cert_file" env:"ETCD_PEER_CERT_FILE"`
PeerKeyFile string `yaml:"peer_key_file" env:"ETCD_PEER_KEY_FILE"`
PeerClientCertAuth bool `yaml:"peer_client_cert_auth" env:"ETCD_PEER_CLIENT_CERT_AUTH"`
PeerTrustedCAFile string `yaml:"peer_trusted_ca_file" env:"ETCD_PEER_TRUSTED_CA_FILE"`
Proxy string `yaml:"proxy" env:"ETCD_PROXY" valid:"^(on|off|readonly)$"`
ProxyDialTimeout int `yaml:"proxy_dial_timeout" env:"ETCD_PROXY_DIAL_TIMEOUT"`
ProxyFailureWait int `yaml:"proxy_failure_wait" env:"ETCD_PROXY_FAILURE_WAIT"`
ProxyReadTimeout int `yaml:"proxy_read_timeout" env:"ETCD_PROXY_READ_TIMEOUT"`
ProxyRefreshInterval int `yaml:"proxy_refresh_interval" env:"ETCD_PROXY_REFRESH_INTERVAL"`
ProxyWriteTimeout int `yaml:"proxy_write_timeout" env:"ETCD_PROXY_WRITE_TIMEOUT"`
SnapshotCount int `yaml:"snapshot_count" env:"ETCD_SNAPSHOT_COUNT"`
TrustedCAFile string `yaml:"trusted_ca_file" env:"ETCD_TRUSTED_CA_FILE"`
WalDir string `yaml:"wal_dir" env:"ETCD_WAL_DIR"`
}

View File

@@ -1,25 +1,23 @@
/* // Copyright 2015 CoreOS, Inc.
Copyright 2014 CoreOS, Inc. //
// Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License. // You may obtain a copy of the License at
You may obtain a copy of the License at //
// http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0 //
// Unless required by applicable law or agreed to in writing, software
Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS,
distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and
See the License for the specific language governing permissions and // limitations under the License.
limitations under the License.
*/
package config package config
type File struct { type File struct {
Encoding string `yaml:"-"` Encoding string `yaml:"encoding" valid:"^(base64|b64|gz|gzip|gz\\+base64|gzip\\+base64|gz\\+b64|gzip\\+b64)$"`
Content string `yaml:"content"` Content string `yaml:"content"`
Owner string `yaml:"owner"` Owner string `yaml:"owner"`
Path string `yaml:"path"` Path string `yaml:"path"`
RawFilePermissions string `yaml:"permissions"` RawFilePermissions string `yaml:"permissions" valid:"^0?[0-7]{3,4}$"`
} }

69
config/file_test.go Normal file
View File

@@ -0,0 +1,69 @@
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"testing"
)
func TestEncodingValid(t *testing.T) {
tests := []struct {
value string
isValid bool
}{
{value: "base64", isValid: true},
{value: "b64", isValid: true},
{value: "gz", isValid: true},
{value: "gzip", isValid: true},
{value: "gz+base64", isValid: true},
{value: "gzip+base64", isValid: true},
{value: "gz+b64", isValid: true},
{value: "gzip+b64", isValid: true},
{value: "gzzzzbase64", isValid: false},
{value: "gzipppbase64", isValid: false},
{value: "unknown", isValid: false},
}
for _, tt := range tests {
isValid := (nil == AssertStructValid(File{Encoding: tt.value}))
if tt.isValid != isValid {
t.Errorf("bad assert (%s): want %t, got %t", tt.value, tt.isValid, isValid)
}
}
}
func TestRawFilePermissionsValid(t *testing.T) {
tests := []struct {
value string
isValid bool
}{
{value: "744", isValid: true},
{value: "0744", isValid: true},
{value: "1744", isValid: true},
{value: "01744", isValid: true},
{value: "11744", isValid: false},
{value: "rwxr--r--", isValid: false},
{value: "800", isValid: false},
}
for _, tt := range tests {
isValid := (nil == AssertStructValid(File{RawFilePermissions: tt.value}))
if tt.isValid != isValid {
t.Errorf("bad assert (%s): want %t, got %t", tt.value, tt.isValid, isValid)
}
}
}

27
config/flannel.go Normal file
View File

@@ -0,0 +1,27 @@
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
type Flannel struct {
EtcdEndpoints string `yaml:"etcd_endpoints" env:"FLANNELD_ETCD_ENDPOINTS"`
EtcdCAFile string `yaml:"etcd_cafile" env:"FLANNELD_ETCD_CAFILE"`
EtcdCertFile string `yaml:"etcd_certfile" env:"FLANNELD_ETCD_CERTFILE"`
EtcdKeyFile string `yaml:"etcd_keyfile" env:"FLANNELD_ETCD_KEYFILE"`
EtcdPrefix string `yaml:"etcd_prefix" env:"FLANNELD_ETCD_PREFIX"`
IPMasq string `yaml:"ip_masq" env:"FLANNELD_IP_MASQ"`
SubnetFile string `yaml:"subnet_file" env:"FLANNELD_SUBNET_FILE"`
Iface string `yaml:"interface" env:"FLANNELD_IFACE"`
PublicIP string `yaml:"public_ip" env:"FLANNELD_PUBLIC_IP"`
}

View File

@@ -1,30 +1,33 @@
/* // Copyright 2015 CoreOS, Inc.
Copyright 2014 CoreOS, Inc. //
// Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License. // You may obtain a copy of the License at
You may obtain a copy of the License at //
// http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0 //
// Unless required by applicable law or agreed to in writing, software
Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS,
distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and
See the License for the specific language governing permissions and // limitations under the License.
limitations under the License.
*/
package config package config
type Fleet struct { type Fleet struct {
AgentTTL string `yaml:"agent-ttl" env:"FLEET_AGENT_TTL"` AgentTTL string `yaml:"agent_ttl" env:"FLEET_AGENT_TTL"`
EngineReconcileInterval string `yaml:"engine-reconcile-interval" env:"FLEET_ENGINE_RECONCILE_INTERVAL"` AuthorizedKeysFile string `yaml:"authorized_keys_file" env:"FLEET_AUTHORIZED_KEYS_FILE"`
EtcdCAFile string `yaml:"etcd-cafile" env:"FLEET_ETCD_CAFILE"` DisableEngine bool `yaml:"disable_engine" env:"FLEET_DISABLE_ENGINE"`
EtcdCertFile string `yaml:"etcd-certfile" env:"FLEET_ETCD_CERTFILE"` EngineReconcileInterval float64 `yaml:"engine_reconcile_interval" env:"FLEET_ENGINE_RECONCILE_INTERVAL"`
EtcdKeyFile string `yaml:"etcd-keyfile" env:"FLEET_ETCD_KEYFILE"` EtcdCAFile string `yaml:"etcd_cafile" env:"FLEET_ETCD_CAFILE"`
EtcdRequestTimeout string `yaml:"etcd-request-timeout" env:"FLEET_ETCD_REQUEST_TIMEOUT"` EtcdCertFile string `yaml:"etcd_certfile" env:"FLEET_ETCD_CERTFILE"`
EtcdServers string `yaml:"etcd-servers" env:"FLEET_ETCD_SERVERS"` EtcdKeyFile string `yaml:"etcd_keyfile" env:"FLEET_ETCD_KEYFILE"`
EtcdKeyPrefix string `yaml:"etcd_key_prefix" env:"FLEET_ETCD_KEY_PREFIX"`
EtcdRequestTimeout float64 `yaml:"etcd_request_timeout" env:"FLEET_ETCD_REQUEST_TIMEOUT"`
EtcdServers string `yaml:"etcd_servers" env:"FLEET_ETCD_SERVERS"`
Metadata string `yaml:"metadata" env:"FLEET_METADATA"` Metadata string `yaml:"metadata" env:"FLEET_METADATA"`
PublicIP string `yaml:"public-ip" env:"FLEET_PUBLIC_IP"` PublicIP string `yaml:"public_ip" env:"FLEET_PUBLIC_IP"`
Verbosity string `yaml:"verbosity" env:"FLEET_VERBOSITY"` TokenLimit int `yaml:"token_limit" env:"FLEET_TOKEN_LIMIT"`
Verbosity int `yaml:"verbosity" env:"FLEET_VERBOSITY"`
VerifyUnits bool `yaml:"verify_units" env:"FLEET_VERIFY_UNITS"`
} }

26
config/ignition.go Normal file
View File

@@ -0,0 +1,26 @@
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"encoding/json"
)
func IsIgnitionConfig(userdata string) bool {
var cfg struct {
Version *int `json:"ignitionVersion" yaml:"ignition_version"`
}
return (json.Unmarshal([]byte(userdata), &cfg) == nil && cfg.Version != nil)
}

25
config/locksmith.go Normal file
View File

@@ -0,0 +1,25 @@
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
type Locksmith struct {
Endpoint string `yaml:"endpoint" env:"LOCKSMITHD_ENDPOINT"`
EtcdCAFile string `yaml:"etcd_cafile" env:"LOCKSMITHD_ETCD_CAFILE"`
EtcdCertFile string `yaml:"etcd_certfile" env:"LOCKSMITHD_ETCD_CERTFILE"`
EtcdKeyFile string `yaml:"etcd_keyfile" env:"LOCKSMITHD_ETCD_KEYFILE"`
Group string `yaml:"group" env:"LOCKSMITHD_GROUP"`
RebootWindowStart string `yaml:"window_start" env:"REBOOT_WINDOW_START" valid:"^((?i:sun|mon|tue|wed|thu|fri|sat|sun) )?0*([0-9]|1[0-9]|2[0-3]):0*([0-9]|[1-5][0-9])$"`
RebootWindowLength string `yaml:"window_length" env:"REBOOT_WINDOW_LENGTH" valid:"^[-+]?([0-9]*(\\.[0-9]*)?[a-z]+)+$"`
}

76
config/locksmith_test.go Normal file
View File

@@ -0,0 +1,76 @@
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"testing"
)
func TestRebootWindowStart(t *testing.T) {
tests := []struct {
value string
isValid bool
}{
{value: "Sun 0:0", isValid: true},
{value: "Sun 00:00", isValid: true},
{value: "sUn 23:59", isValid: true},
{value: "mon 0:0", isValid: true},
{value: "tue 0:0", isValid: true},
{value: "tues 0:0", isValid: false},
{value: "wed 0:0", isValid: true},
{value: "thu 0:0", isValid: true},
{value: "thur 0:0", isValid: false},
{value: "fri 0:0", isValid: true},
{value: "sat 0:0", isValid: true},
{value: "sat00:00", isValid: false},
{value: "00:00", isValid: true},
{value: "10:10", isValid: true},
{value: "20:20", isValid: true},
{value: "20:30", isValid: true},
{value: "20:40", isValid: true},
{value: "20:50", isValid: true},
{value: "20:60", isValid: false},
{value: "24:00", isValid: false},
}
for _, tt := range tests {
isValid := (nil == AssertStructValid(Locksmith{RebootWindowStart: tt.value}))
if tt.isValid != isValid {
t.Errorf("bad assert (%s): want %t, got %t", tt.value, tt.isValid, isValid)
}
}
}
func TestRebootWindowLength(t *testing.T) {
tests := []struct {
value string
isValid bool
}{
{value: "1h", isValid: true},
{value: "1d", isValid: true},
{value: "0d", isValid: true},
{value: "0.5h", isValid: true},
{value: "0.5.0h", isValid: false},
}
for _, tt := range tests {
isValid := (nil == AssertStructValid(Locksmith{RebootWindowLength: tt.value}))
if tt.isValid != isValid {
t.Errorf("bad assert (%s): want %t, got %t", tt.value, tt.isValid, isValid)
}
}
}

View File

@@ -1,25 +1,23 @@
/* // Copyright 2015 CoreOS, Inc.
Copyright 2014 CoreOS, Inc. //
// Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License. // You may obtain a copy of the License at
You may obtain a copy of the License at //
// http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0 //
// Unless required by applicable law or agreed to in writing, software
Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS,
distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and
See the License for the specific language governing permissions and // limitations under the License.
limitations under the License.
*/
package config package config
type OEM struct { type OEM struct {
ID string `yaml:"id"` ID string `yaml:"id"`
Name string `yaml:"name"` Name string `yaml:"name"`
VersionID string `yaml:"version-id"` VersionID string `yaml:"version_id"`
HomeURL string `yaml:"home-url"` HomeURL string `yaml:"home_url"`
BugReportURL string `yaml:"bug-report-url"` BugReportURL string `yaml:"bug_report_url"`
} }

31
config/script.go Normal file
View File

@@ -0,0 +1,31 @@
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"strings"
)
type Script []byte
func IsScript(userdata string) bool {
header := strings.SplitN(userdata, "\n", 2)[0]
return strings.HasPrefix(header, "#!")
}
func NewScript(userdata string) (*Script, error) {
s := Script(userdata)
return &s, nil
}

View File

@@ -1,50 +1,30 @@
/* // Copyright 2015 CoreOS, Inc.
Copyright 2014 CoreOS, Inc. //
// Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License. // You may obtain a copy of the License at
You may obtain a copy of the License at //
// http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0 //
// Unless required by applicable law or agreed to in writing, software
Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS,
distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and
See the License for the specific language governing permissions and // limitations under the License.
limitations under the License.
*/
package config package config
import (
"path/filepath"
"strings"
)
type Unit struct { type Unit struct {
Name string `yaml:"name"` Name string `yaml:"name"`
Mask bool `yaml:"mask"` Mask bool `yaml:"mask"`
Enable bool `yaml:"enable"` Enable bool `yaml:"enable"`
Runtime bool `yaml:"runtime"` Runtime bool `yaml:"runtime"`
Content string `yaml:"content"` Content string `yaml:"content"`
Command string `yaml:"command"` Command string `yaml:"command" valid:"^(start|stop|restart|reload|try-restart|reload-or-restart|reload-or-try-restart)$"`
DropIns []UnitDropIn `yaml:"drop_ins"`
// For drop-in units, a cloudinit.conf is generated.
// This is currently unbound in YAML (and hence unsettable in cloud-config files)
// until the correct behaviour for multiple drop-in units is determined.
DropIn bool `yaml:"-"`
} }
func (u *Unit) Type() string { type UnitDropIn struct {
ext := filepath.Ext(u.Name) Name string `yaml:"name"`
return strings.TrimLeft(ext, ".") Content string `yaml:"content"`
}
func (u *Unit) Group() string {
switch u.Type() {
case "network", "netdev", "link":
return "network"
default:
return "system"
}
} }

46
config/unit_test.go Normal file
View File

@@ -0,0 +1,46 @@
/*
Copyright 2014 CoreOS, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config
import (
"testing"
)
func TestCommandValid(t *testing.T) {
tests := []struct {
value string
isValid bool
}{
{value: "start", isValid: true},
{value: "stop", isValid: true},
{value: "restart", isValid: true},
{value: "reload", isValid: true},
{value: "try-restart", isValid: true},
{value: "reload-or-restart", isValid: true},
{value: "reload-or-try-restart", isValid: true},
{value: "tryrestart", isValid: false},
{value: "unknown", isValid: false},
}
for _, tt := range tests {
isValid := (nil == AssertStructValid(Unit{Command: tt.value}))
if tt.isValid != isValid {
t.Errorf("bad assert (%s): want %t, got %t", tt.value, tt.isValid, isValid)
}
}
}

View File

@@ -1,23 +1,21 @@
/* // Copyright 2015 CoreOS, Inc.
Copyright 2014 CoreOS, Inc. //
// Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License. // You may obtain a copy of the License at
You may obtain a copy of the License at //
// http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0 //
// Unless required by applicable law or agreed to in writing, software
Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS,
distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and
See the License for the specific language governing permissions and // limitations under the License.
limitations under the License.
*/
package config package config
type Update struct { type Update struct {
RebootStrategy string `yaml:"reboot-strategy" env:"REBOOT_STRATEGY" valid:"best-effort,etcd-lock,reboot,off"` RebootStrategy string `yaml:"reboot_strategy" env:"REBOOT_STRATEGY" valid:"^(best-effort|etcd-lock|reboot|off)$"`
Group string `yaml:"group" env:"GROUP"` Group string `yaml:"group" env:"GROUP"`
Server string `yaml:"server" env:"SERVER"` Server string `yaml:"server" env:"SERVER"`
} }

43
config/update_test.go Normal file
View File

@@ -0,0 +1,43 @@
/*
Copyright 2014 CoreOS, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config
import (
"testing"
)
func TestRebootStrategyValid(t *testing.T) {
tests := []struct {
value string
isValid bool
}{
{value: "best-effort", isValid: true},
{value: "etcd-lock", isValid: true},
{value: "reboot", isValid: true},
{value: "off", isValid: true},
{value: "besteffort", isValid: false},
{value: "unknown", isValid: false},
}
for _, tt := range tests {
isValid := (nil == AssertStructValid(Update{RebootStrategy: tt.value}))
if tt.isValid != isValid {
t.Errorf("bad assert (%s): want %t, got %t", tt.value, tt.isValid, isValid)
}
}
}

View File

@@ -1,33 +1,34 @@
/* // Copyright 2015 CoreOS, Inc.
Copyright 2014 CoreOS, Inc. //
// Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License. // You may obtain a copy of the License at
You may obtain a copy of the License at //
// http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0 //
// Unless required by applicable law or agreed to in writing, software
Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS,
distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and
See the License for the specific language governing permissions and // limitations under the License.
limitations under the License.
*/
package config package config
type User struct { type User struct {
Name string `yaml:"name"` Name string `yaml:"name"`
PasswordHash string `yaml:"passwd"` PasswordHash string `yaml:"passwd"`
SSHAuthorizedKeys []string `yaml:"ssh-authorized-keys"` SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"`
SSHImportGithubUser string `yaml:"coreos-ssh-import-github"` SSHImportGithubUser string `yaml:"coreos_ssh_import_github" deprecated:"trying to fetch from a remote endpoint introduces too many intermittent errors"`
SSHImportURL string `yaml:"coreos-ssh-import-url"` SSHImportGithubUsers []string `yaml:"coreos_ssh_import_github_users" deprecated:"trying to fetch from a remote endpoint introduces too many intermittent errors"`
SSHImportURL string `yaml:"coreos_ssh_import_url" deprecated:"trying to fetch from a remote endpoint introduces too many intermittent errors"`
GECOS string `yaml:"gecos"` GECOS string `yaml:"gecos"`
Homedir string `yaml:"homedir"` Homedir string `yaml:"homedir"`
NoCreateHome bool `yaml:"no-create-home"` NoCreateHome bool `yaml:"no_create_home"`
PrimaryGroup string `yaml:"primary-group"` LockPasswd bool `yaml:"lock_passwd"`
PrimaryGroup string `yaml:"primary_group"`
Groups []string `yaml:"groups"` Groups []string `yaml:"groups"`
NoUserGroup bool `yaml:"no-user-group"` NoUserGroup bool `yaml:"no_user_group"`
System bool `yaml:"system"` System bool `yaml:"system"`
NoLogInit bool `yaml:"no-log-init"` NoLogInit bool `yaml:"no_log_init"`
Shell string `yaml:"shell"`
} }

Some files were not shown because too many files have changed in this diff Show More