Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / core / monojob.c
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <string.h>
23 #include <stdio.h>
24 #include <errno.h>
25 #include <ipxe/process.h>
26 #include <ipxe/console.h>
27 #include <ipxe/keys.h>
28 #include <ipxe/job.h>
29 #include <ipxe/monojob.h>
30 #include <ipxe/timer.h>
31
32 /** @file
33  *
34  * Single foreground job
35  *
36  */
37
38 static int monojob_rc;
39
40 static void monojob_close ( struct interface *intf, int rc ) {
41         monojob_rc = rc;
42         intf_restart ( intf, rc );
43 }
44
45 static struct interface_operation monojob_intf_op[] = {
46         INTF_OP ( intf_close, struct interface *, monojob_close ),
47 };
48
49 static struct interface_descriptor monojob_intf_desc =
50         INTF_DESC_PURE ( monojob_intf_op );
51
52 struct interface monojob = INTF_INIT ( monojob_intf_desc );
53
54 /**
55  * Wait for single foreground job to complete
56  *
57  * @v string            Job description to display, or NULL to be silent
58  * @v timeout           Timeout period, in ticks (0=indefinite)
59  * @ret rc              Job final status code
60  */
61 int monojob_wait ( const char *string, unsigned long timeout ) {
62         struct job_progress progress;
63         unsigned long last_keycheck;
64         unsigned long last_progress;
65         unsigned long last_display;
66         unsigned long now;
67         unsigned long elapsed;
68         unsigned long completed = 0;
69         unsigned long scaled_completed;
70         unsigned long scaled_total;
71         unsigned int percentage;
72         int shown_percentage = 0;
73         int ongoing_rc;
74         int key;
75         int rc;
76
77         if ( string )
78                 printf ( "%s...", string );
79         monojob_rc = -EINPROGRESS;
80         last_keycheck = last_progress = last_display = currticks();
81         while ( monojob_rc == -EINPROGRESS ) {
82
83                 /* Allow job to progress */
84                 step();
85                 now = currticks();
86
87                 /* Check for keypresses.  This can be time-consuming,
88                  * so check only once per clock tick.
89                  */
90                 elapsed = ( now - last_keycheck );
91                 if ( elapsed ) {
92                         if ( iskey() ) {
93                                 key = getchar();
94                                 if ( key == CTRL_C ) {
95                                         monojob_rc = -ECANCELED;
96                                         break;
97                                 }
98                         }
99                         last_keycheck = now;
100                 }
101
102                 /* Monitor progress */
103                 ongoing_rc = job_progress ( &monojob, &progress );
104
105                 /* Reset timeout if progress has been made */
106                 if ( completed != progress.completed )
107                         last_progress = now;
108                 completed = progress.completed;
109
110                 /* Check for timeout, if applicable */
111                 elapsed = ( now - last_progress );
112                 if ( timeout && ( elapsed >= timeout ) ) {
113                         monojob_rc = ( ongoing_rc ? ongoing_rc : -ETIMEDOUT );
114                         break;
115                 }
116
117                 /* Display progress, if applicable */
118                 elapsed = ( now - last_display );
119                 if ( string && ( elapsed >= TICKS_PER_SEC ) ) {
120                         if ( shown_percentage )
121                                 printf ( "\b\b\b\b    \b\b\b\b" );
122                         /* Normalise progress figures to avoid overflow */
123                         scaled_completed = ( progress.completed / 128 );
124                         scaled_total = ( progress.total / 128 );
125                         if ( scaled_total ) {
126                                 percentage = ( ( 100 * scaled_completed ) /
127                                                scaled_total );
128                                 printf ( "%3d%%", percentage );
129                                 shown_percentage = 1;
130                         } else {
131                                 printf ( "." );
132                                 shown_percentage = 0;
133                         }
134                         last_display = now;
135                 }
136         }
137         rc = monojob_rc;
138         monojob_close ( &monojob, rc );
139
140         if ( shown_percentage )
141                 printf ( "\b\b\b\b    \b\b\b\b" );
142
143         if ( string ) {
144                 if ( rc ) {
145                         printf ( " %s\n", strerror ( rc ) );
146                 } else {
147                         printf ( " ok\n" );
148                 }
149         }
150
151         return rc;
152 }