summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdiskfs/boot-parse.c98
1 files changed, 88 insertions, 10 deletions
diff --git a/libdiskfs/boot-parse.c b/libdiskfs/boot-parse.c
index 4403fcfe..58685464 100644
--- a/libdiskfs/boot-parse.c
+++ b/libdiskfs/boot-parse.c
@@ -24,6 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <device/device.h>
#include <string.h>
#include <sys/reboot.h>
+#include <mach/mig_support.h>
int diskfs_bootflags;
char *diskfs_bootflagarg;
@@ -40,19 +41,96 @@ diskfs_parse_bootargs (int argc, char **argv)
{
char *devname;
device_t con;
-
- /* The arguments, as passed by the kernel, are as follows:
- -<flags> hostport deviceport rootname */
+ mach_port_t bootstrap;
+
+ task_get_bootstrap_port (mach_task_self (), &bootstrap);
+ if (bootstrap != MACH_PORT_NULL)
+ {
+ /* We were started not by the kernel, but by the CMU default_pager.
+ It passes us args: -<flags> root_name server_dir_name. We ignore
+ the last one. An RPC on our bootstrap port fetches the privileged
+ ports. */
+
+ struct
+ {
+ mach_msg_header_t Head;
+ mach_msg_type_t priv_hostType;
+ mach_port_t priv_host;
+ mach_msg_type_t priv_deviceType;
+ mach_port_t priv_device;
+ } msg;
+ mach_msg_return_t msg_result;
+
+ static const mach_msg_type_t portCheck = {
+ /* msgt_name = */ MACH_MSG_TYPE_MOVE_SEND,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ msg.Head.msgh_bits =
+ MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
+ /* msgh_size passed as argument */
+ msg.Head.msgh_remote_port = bootstrap;
+ msg.Head.msgh_local_port = mig_get_reply_port ();
+ msg.Head.msgh_seqno = 0;
+ msg.Head.msgh_id = 999999;
- if (argc != 5 || argv[1][0] != '-')
+ msg_result = mach_msg(&msg.Head, MACH_SEND_MSG|MACH_RCV_MSG,
+ sizeof msg.Head, sizeof msg,
+ msg.Head.msgh_local_port,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if (msg_result != MACH_MSG_SUCCESS)
+ {
+ if ((msg_result == MACH_SEND_INVALID_REPLY) ||
+ (msg_result == MACH_SEND_INVALID_MEMORY) ||
+ (msg_result == MACH_SEND_INVALID_RIGHT) ||
+ (msg_result == MACH_SEND_INVALID_TYPE) ||
+ (msg_result == MACH_SEND_MSG_TOO_SMALL) ||
+ (msg_result == MACH_RCV_INVALID_NAME))
+ mig_dealloc_reply_port (msg.Head.msgh_local_port);
+ else
+ mig_put_reply_port (msg.Head.msgh_local_port);
+ assert (msg_result == MACH_MSG_SUCCESS);
+ }
+ mig_put_reply_port (msg.Head.msgh_local_port);
+
+ assert (msg.Head.msgh_id == 999999 + 100);
+ assert (msg.Head.msgh_size == sizeof msg);
+ assert (msg.Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);
+ assert (*(int *) &msg.priv_hostType == *(int *) &portCheck);
+ assert (*(int *) &msg.priv_deviceType == *(int *) &portCheck);
+ diskfs_host_priv = msg.priv_host;
+ diskfs_master_device = msg.priv_device;
+
+ /* bootstrap_privileged_ports (bootstrap,
+ &diskfs_host_priv,
+ &diskfs_master_device); */
+
+ /* Clear our bootstrap port, to appear as if run by the kernel. */
+ task_set_bootstrap_port (mach_task_self (), MACH_PORT_NULL);
+
+ devname = argv[2];
+ }
+ else
{
- fprintf (stderr, "Usage: %s: -[qsdnx] hostport deviceport rootname\n",
- program_invocation_name);
- exit (1);
+ /* The arguments, as passed by the kernel, are as follows:
+ -<flags> hostport deviceport rootname */
+
+ if (argc != 5 || argv[1][0] != '-')
+ {
+ fprintf (stderr,
+ "Usage: %s: -[qsdnx] hostport deviceport rootname\n",
+ program_invocation_name);
+ exit (1);
+ }
+ diskfs_host_priv = atoi (argv[2]);
+ diskfs_master_device = atoi (argv[3]);
+ devname = argv[4];
}
- diskfs_host_priv = atoi (argv[2]);
- diskfs_master_device = atoi (argv[3]);
- devname = argv[4];
(void) device_open (diskfs_master_device, D_WRITE, "console", &con);
stderr = stdout = mach_open_devstream (con, "w");