Merge tag 'upstream/3.14'
[debian/elilo] / devschemes / simple.c
1 /*
2  *  Copyright (C) 2001-2003 Hewlett-Packard Co.
3  *      Contributed by Stephane Eranian <eranian@hpl.hp.com>
4  *
5  * This file is part of the ELILO, the EFI Linux boot loader.
6  *
7  *  ELILO is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2, or (at your option)
10  *  any later version.
11  *
12  *  ELILO is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with ELILO; see the file COPYING.  If not, write to the Free
19  *  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20  *  02111-1307, USA.
21  *
22  * Look at the README.devschemes for more explanations on how
23  * to use devschemes.
24  */
25
26 #include <efi.h>
27 #include <efilib.h>
28
29 #include "elilo.h"
30 #include "fileops.h"
31
32 #define NAMING_SCHEME   L"simple"
33
34 typedef struct {
35         INT8 type;
36         INT8 subtype;
37         INTN (*device_func)(device_t *dev, EFI_DEVICE_PATH *dp);
38 } devices_types_t;
39
40
41 static UINT32 atapi_count, scsi_count, net_count;
42
43 static INTN
44 atapi_device(device_t *dev, EFI_DEVICE_PATH *dp)
45 {
46         //ATAPI_DEVICE_PATH *atapi = (ATAPI_DEVICE_PATH *)dp;
47
48         dev->name[0] = L'a';
49         dev->name[1] = L't';
50         dev->name[2] = L'a';
51         dev->name[3] = L'p';
52         dev->name[4] = L'i';
53
54         SPrint(dev->name+5,FILEOPS_DEVNAME_MAXLEN-5-1,  L"%d", atapi_count);
55         atapi_count++;
56
57         return 0;
58 }
59
60 static INTN
61 scsi_device(device_t *dev, EFI_DEVICE_PATH *dp)
62 {
63         //SCSI_DEVICE_PATH *scsi = (SCSI_DEVICE_PATH *)dp;
64
65         dev->name[0]   = L's';
66         dev->name[1]   = L'c';
67         dev->name[2]   = L's';
68         dev->name[3]   = L'i';
69
70         SPrint(dev->name+4, FILEOPS_DEVNAME_MAXLEN-4-1, L"%d", scsi_count);
71         scsi_count++;
72
73         return 0;
74 }
75
76 static INTN
77 network_device(device_t *dev, EFI_DEVICE_PATH *dp)
78 {
79         //MAC_ADDR_DEVICE_PATH *mac = (MAC_ADDR_DEVICE_PATH *)dp;
80
81         dev->name[0] = L'n';
82         dev->name[1] = L'e';
83         dev->name[2] = L't';
84
85         SPrint(dev->name+3, FILEOPS_DEVNAME_MAXLEN-3-1, L"%d", net_count);
86         net_count++;
87
88         return 0;
89 }
90
91 /*
92  * what we are looking for in the device path
93  */
94 static devices_types_t dev_types[]={
95         { MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, atapi_device},
96         { MESSAGING_DEVICE_PATH, MSG_SCSI_DP, scsi_device},
97         { MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, network_device},
98         { 0, 0 , NULL}
99 };
100
101 static INTN
102 simple_scheme(device_t *tab, UINTN n)
103 {
104         EFI_DEVICE_PATH *dp1, *dp;
105         devices_types_t *p;
106         UINTN i;
107
108         /*
109          * note that this test is necessary but not sufficient to guarantee that this scheme
110          * will work because, we have no way of detecting that the machine got actually
111          * rebooted if the EDD30 variable was forced. this comes from the fact, that elilo
112          * can be invoked once, aborted and then restarted with no machine reboot.
113          *
114          * XXX: there may be a way to detect this with the another variable which would
115          * be in volatile memory only
116          */
117         if (elilo_opt.edd30_on == 0) {
118                 VERB_PRT(4, Print(L"%s device naming scheme only works with EDD3.0 enabled\n", NAMING_SCHEME));
119                 return -1;
120         }
121
122         for(i=0; i < n; i++) {
123                 dp = DevicePathFromHandle(tab[i].dev);
124                 if (dp == NULL) {
125                         ERR_PRT((L"cannot get device path for device %d", i));
126                         continue;
127                 }
128                 dp1 = dp = UnpackDevicePath(dp);
129
130                 while (!IsDevicePathEnd(dp)) {
131                         p = dev_types;
132                         while (p->type) {
133                                 if (   p->type == DevicePathType(dp) 
134                                     && p->subtype == DevicePathSubType(dp)) {
135                                         (*p->device_func)(tab+i, dp);
136                                         goto done;
137                                 }
138
139                                 p++;
140                         }
141                         dp = NextDevicePathNode(dp);
142                 }
143 done:
144                 FreePool(dp1); 
145         }
146         return 0;
147 }
148
149 devname_scheme_t simple_devname_scheme={
150         NAMING_SCHEME,
151         simple_scheme
152 };