2 # Copyright (c) 2005 IBM Corporation
3 # Copyright (c) 2005 XenSource Ltd.
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of version 2.1 of the GNU Lesser General Public
7 # License as published by the Free Software Foundation.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 VTPMDB="/var/vtpm/vtpm.db"
25 #In the vtpm-impl file some commands should be defined:
26 # vtpm_create, vtpm_setup, vtpm_start, etc. (see below)
27 if [ -r "$dir/vtpm-impl.alt" ]; then
28 . "$dir/vtpm-impl.alt"
29 elif [ -r "$dir/vtpm-impl" ]; then
32 function vtpm_create () {
35 function vtpm_setup() {
38 function vtpm_start() {
41 function vtpm_suspend() {
44 function vtpm_resume() {
47 function vtpm_delete() {
50 function vtpm_migrate() {
51 echo "Error: vTPM migration accross machines not implemented."
53 function vtpm_migrate_local() {
54 echo "Error: local vTPM migration not supported"
56 function vtpm_migrate_recover() {
62 #Find the instance number for the vtpm given the name of the domain
64 # - vmname : the name of the vm
66 # Returns '0' if instance number could not be found, otherwise
67 # it returns the instance number in the variable 'instance'
68 function vtpmdb_find_instance () {
69 local vmname ret instance
73 instance=$(cat $VTPMDB | \
74 awk -vvmname=$vmname \
76 if ( 1 != index($1,"#")) { \
77 if ( $1 == vmname ) { \
83 if [ "$instance" != "" ]; then
90 # Check whether a particular instance number is still available
91 # returns "0" if it is not available, "1" otherwise.
92 function vtpmdb_is_free_instancenum () {
93 local instance instances avail i
96 #Allowed instance number range: 1-255
97 if [ $instance -eq 0 -o $instance -gt 255 ]; then
100 instances=$(cat $VTPMDB | \
103 if (1 != index($1,"#")) { \
107 for i in $instances; do
108 if [ $i -eq $instance ]; then
118 # Get an available instance number given the database
119 # Returns an unused instance number
120 function vtpmdb_get_free_instancenum () {
121 local ctr instances don found
122 instances=$(cat $VTPMDB | \
125 if (1 != index($1,"#")) { \
131 while [ $don -eq 0 ]; do
133 for i in $instances; do
134 if [ $i -eq $ctr ]; then
140 if [ $found -eq 0 ]; then
150 # Add a domain name and instance number to the DB file
151 function vtpmdb_add_instance () {
152 local res vmname inst
156 if [ ! -f $VTPMDB ]; then
157 echo "#Database for VM to vTPM association" > $VTPMDB
158 echo "#1st column: domain name" >> $VTPMDB
159 echo "#2nd column: TPM instance number" >> $VTPMDB
161 res=$(vtpmdb_validate_entry $vmname $inst)
162 if [ $res -eq 0 ]; then
163 echo "$vmname $inst" >> $VTPMDB
168 #Validate whether an entry is the same as passed to this
170 function vtpmdb_validate_entry () {
171 local res rc vmname inst
176 res=$(cat $VTPMDB | \
177 gawk -vvmname=$vmname \
180 if ( 1 == index($1,"#")) {\
182 if ( $1 == vmname && \
187 if ( $1 == vmname || \
194 if [ "$res" == "1" ]; then
196 elif [ "$res" == "2" ]; then
203 #Remove an entry from the vTPM database given its domain name
205 function vtpmdb_remove_entry () {
206 local vmname instance VTPMDB_TMP
209 VTPMDB_TMP="$VTPMDB".tmp
212 gawk -vvmname=$vmname \
214 if ( $1 != vmname ) { \
218 if [ -e $VTPMDB_TMP ]; then
219 mv -f $VTPMDB_TMP $VTPMDB
220 vtpm_delete $instance
222 log err "Error creating temporary file '$VTPMDB_TMP'."
227 # Find the reason for the creation of this device:
228 # Returns 'resume' or 'create'
229 function vtpm_get_create_reason () {
231 resume=$(xenstore_read $XENBUS_PATH/resume)
232 if [ "$resume" == "True" ]; then
240 #Create a vTPM instance
241 # If no entry in the TPM database is found, the instance is
242 # created and an entry added to the database.
243 function vtpm_create_instance () {
244 local res instance domname reason uuid
245 uuid=$(xenstore_read "$XENBUS_PATH"/uuid)
246 reason=$(vtpm_get_create_reason)
252 if [ "$uuid" != "" ]; then
253 instance=$(vtpmdb_find_instance $uuid)
255 if [ "$instance" == "0" ]; then
256 domname=$(xenstore_read "$XENBUS_PATH"/domain)
257 instance=$(vtpmdb_find_instance $domname)
260 if [ "$instance" == "0" -a "$reason" != "create" ]; then
265 if [ "$instance" == "0" ]; then
266 #Try to give the preferred instance to the domain
267 instance=$(xenstore_read "$XENBUS_PATH"/pref_instance)
268 if [ "$instance" != "" ]; then
269 res=$(vtpmdb_is_free_instancenum $instance)
270 if [ $res -eq 0 ]; then
271 instance=$(vtpmdb_get_free_instancenum)
274 instance=$(vtpmdb_get_free_instancenum)
277 vtpm_create $instance
279 if [ $vtpm_fatal_error -eq 0 ]; then
280 if [ "$uuid" != "" ]; then
281 vtpmdb_add_instance $uuid $instance
283 vtpmdb_add_instance $domname $instance
287 if [ "$reason" == "resume" ]; then
288 vtpm_resume $instance
296 xenstore_write $XENBUS_PATH/instance $instance
300 #Remove an instance when a VM is terminating or suspending.
301 #Since it is assumed that the VM will appear again, the
302 #entry is kept in the VTPMDB file.
303 function vtpm_remove_instance () {
304 local instance reason domname uuid
305 #Stop script execution quietly if path does not exist (anymore)
306 xenstore-exists "$XENBUS_PATH"/domain
307 uuid=$(xenstore_read "$XENBUS_PATH"/uuid)
313 if [ "$uuid" != "" ]; then
314 instance=$(vtpmdb_find_instance $uuid)
317 if [ "$instance" == "0" ]; then
318 domname=$(xenstore_read "$XENBUS_PATH"/domain)
319 instance=$(vtpmdb_find_instance $domname)
322 if [ "$instance" != "0" ]; then
323 vtpm_suspend $instance
330 #Remove an entry in the VTPMDB file given the domain's name
331 #1st parameter: The name of the domain
332 function vtpm_delete_instance () {
337 instance=$(vtpmdb_find_instance $1)
338 if [ "$instance" != "0" ]; then
339 vtpmdb_remove_entry $1 $instance
345 # Determine whether the given address is local to this machine
347 # "-1" : the given machine name is invalid
348 # "0" : this is not an address of this machine
349 # "1" : this is an address local to this machine
350 function vtpm_isLocalAddress() {
352 addr=$(ping $1 -c 1 | \
353 gawk '{ print substr($3,2,length($3)-2); exit }')
354 if [ "$addr" == "" ]; then
358 res=$(ifconfig | grep "inet addr" | \
361 if ( addr == substr($2, 6)) {\
366 if [ "$res" == "" ]; then
373 # Perform a migration step. This function differentiates between migration
374 # to the local host or to a remote machine.
376 # 1st: destination host to migrate to
377 # 2nd: name of the domain to migrate
378 # 3rd: the migration step to perform
379 function vtpm_migration_step() {
380 local res=$(vtpm_isLocalAddress $1)
381 if [ "$res" == "0" ]; then
382 vtpm_migrate $1 $2 $3
388 # Recover from migration due to an error. This function differentiates
389 # between migration to the local host or to a remote machine.
391 # 1st: destination host the migration was going to
392 # 2nd: name of the domain that was to be migrated
393 # 3rd: the last successful migration step that was done
394 function vtpm_recover() {
396 res=$(vtpm_isLocalAddress $1)
397 if [ "$res" == "0" ]; then
398 vtpm_migrate_recover $1 $2 $3
403 #Determine the domain id given a domain's name.
404 #1st parameter: name of the domain
405 #return value: domain id or -1 if domain id could not be determined
406 function vtpm_domid_from_name () {
408 ids=$(xenstore-list /local/domain)
410 name=$(xenstore-read /local/domain/$id/name)
411 if [ "$name" == "$1" ]; then
419 #Determine the virtual TPM's instance number using the domain ID.
421 function vtpm_uuid_by_domid() {
422 echo $(xenstore-read /local/domain/0/backend/vtpm/$1/0/uuid)
426 # Determine the vTPM's UUID by the name of the VM
427 function vtpm_uuid_from_vmname() {
428 local domid=$(vtpm_domid_from_name $1)
429 if [ "$domid" != "-1" ]; then
430 echo $(vtpm_uuid_by_domid $domid)
436 #Add a virtual TPM instance number and its associated domain name
437 #to the VTPMDB file and activate usage of this virtual TPM instance
438 #by writing the instance number into the xenstore
439 #1st parm: name of virtual machine
440 #2nd parm: instance of associated virtual TPM
441 function vtpm_add_and_activate() {
442 local domid=$(vtpm_domid_from_name $1)
443 local vtpm_uuid=$(vtpm_uuid_from_vmname $1)
444 if [ "$vtpm_uuid" != "" -a "$domid" != "-1" ]; then
445 vtpmdb_add_instance $vtpm_uuid $2
446 xenstore-write backend/vtpm/$domid/0/instance $2