35 |
/* Allocate space statically, because this is very small anyway. */ |
/* Allocate space statically, because this is very small anyway. */ |
36 |
static char pupa_chainloader_boot_sector[PUPA_DISK_SECTOR_SIZE]; |
static char pupa_chainloader_boot_sector[PUPA_DISK_SECTOR_SIZE]; |
37 |
|
|
38 |
|
static pupa_dl_t my_mod; |
39 |
|
|
40 |
static pupa_err_t |
static pupa_err_t |
41 |
pupa_chainloader_boot (void) |
pupa_chainloader_boot (void) |
42 |
{ |
{ |
77 |
return PUPA_ERR_NONE; |
return PUPA_ERR_NONE; |
78 |
} |
} |
79 |
|
|
80 |
|
static pupa_err_t |
81 |
|
pupa_chainloader_unload (void) |
82 |
|
{ |
83 |
|
pupa_dl_unref (my_mod); |
84 |
|
} |
85 |
|
|
86 |
static void |
static void |
87 |
pupa_rescue_cmd_chainloader (int argc, char *argv[]) |
pupa_rescue_cmd_chainloader (int argc, char *argv[]) |
88 |
{ |
{ |
89 |
pupa_file_t file; |
pupa_file_t file = 0; |
90 |
pupa_uint16_t signature; |
pupa_uint16_t signature; |
91 |
int force = 0; |
int force = 0; |
92 |
|
|
93 |
|
pupa_dl_ref (my_mod); |
94 |
|
|
95 |
if (argc > 0 && pupa_strcmp (argv[0], "--force") == 0) |
if (argc > 0 && pupa_strcmp (argv[0], "--force") == 0) |
96 |
{ |
{ |
97 |
force = 1; |
force = 1; |
102 |
if (argc == 0) |
if (argc == 0) |
103 |
{ |
{ |
104 |
pupa_error (PUPA_ERR_BAD_ARGUMENT, "no file specified"); |
pupa_error (PUPA_ERR_BAD_ARGUMENT, "no file specified"); |
105 |
return; |
goto fail; |
106 |
} |
} |
107 |
|
|
108 |
file = pupa_file_open (argv[0]); |
file = pupa_file_open (argv[0]); |
109 |
if (! file) |
if (! file) |
110 |
return; |
goto fail; |
111 |
|
|
112 |
/* Read the first block. */ |
/* Read the first block. */ |
113 |
if (pupa_file_read (file, pupa_chainloader_boot_sector, |
if (pupa_file_read (file, pupa_chainloader_boot_sector, |
116 |
if (pupa_errno == PUPA_ERR_NONE) |
if (pupa_errno == PUPA_ERR_NONE) |
117 |
pupa_error (PUPA_ERR_BAD_OS, "too small"); |
pupa_error (PUPA_ERR_BAD_OS, "too small"); |
118 |
|
|
119 |
pupa_file_close (file); |
goto fail; |
|
return; |
|
120 |
} |
} |
121 |
|
|
122 |
/* Check the signature. */ |
/* Check the signature. */ |
123 |
signature = *((pupa_uint16_t *) (pupa_chainloader_boot_sector |
signature = *((pupa_uint16_t *) (pupa_chainloader_boot_sector |
124 |
+ PUPA_DISK_SECTOR_SIZE - 2)); |
+ PUPA_DISK_SECTOR_SIZE - 2)); |
125 |
if (signature != pupa_le_to_cpu16 (0xaa55) && ! force) |
if (signature != pupa_le_to_cpu16 (0xaa55) && ! force) |
126 |
pupa_error (PUPA_ERR_BAD_OS, "invalid signature"); |
{ |
127 |
|
pupa_error (PUPA_ERR_BAD_OS, "invalid signature"); |
128 |
|
goto fail; |
129 |
|
} |
130 |
|
|
131 |
pupa_file_close (file); |
pupa_file_close (file); |
132 |
|
pupa_loader_set (0, pupa_chainloader_boot, pupa_chainloader_unload); |
133 |
|
return; |
134 |
|
|
135 |
|
fail: |
136 |
|
|
137 |
if (pupa_errno == PUPA_ERR_NONE) |
if (file) |
138 |
pupa_loader_set (0, pupa_chainloader_boot, 0); |
pupa_file_close (file); |
139 |
|
|
140 |
|
pupa_dl_unref (my_mod); |
141 |
} |
} |
142 |
|
|
143 |
static const char loader_name[] = "chainloader"; |
static const char loader_name[] = "chainloader"; |
147 |
pupa_rescue_register_command (loader_name, |
pupa_rescue_register_command (loader_name, |
148 |
pupa_rescue_cmd_chainloader, |
pupa_rescue_cmd_chainloader, |
149 |
"load another boot loader"); |
"load another boot loader"); |
150 |
|
my_mod = mod; |
151 |
} |
} |
152 |
|
|
153 |
PUPA_MOD_FINI |
PUPA_MOD_FINI |